<commit_before>use grain_capnp::{PowerboxCapability, UiView, UiSession};
use web_session_capnp::{WebSession};

use capnp::capability::{ClientHook, FromServer};
use capnp::AnyPointer;
use capnp_rpc::rpc::{RpcConnectionState, SturdyRefRestorer};
use capnp_rpc::capability::{LocalClient};

pub struct UiViewImpl;

impl PowerboxCapability::Server for UiViewImpl {
    fn get_powerbox_info(&mut self, context : PowerboxCapability::GetPowerboxInfoContext) {
        context.done()
    }
}

impl UiView::Server for UiViewImpl {
    fn get_view_info(&mut self, context : UiView::GetViewInfoContext) {
        context.done()
    }

    fn new_session(&mut self, mut context : UiView::NewSessionContext) {
        println!("asked for a new session!");
        let (_, results) = context.get();

        let client : WebSession::Client = FromServer::new(None::<LocalClient>, ~WebSessionImpl);
        // we need to do this dance to upcast.
        results.set_session(UiSession::Client { client : client.client});

        context.done()
    }
}

pub struct WebSessionImpl;

impl UiSession::Server for WebSessionImpl {

}

static main_css : &'static str =
    "body { font-family: Helvetica, Sans, Arial;
            font-size: medium;
             margin-left: auto;
             margin-right: auto;
             width: 600px;
     }";

static header : &'static str =
  r#"<title> acronymy </title><link rel="stylesheet" type="text/css" href="main.css" >
 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
  "#;

fn html_body(body :&str) -> ~str {
    format!("{}{}", header, body)
}

struct Path {
    path : ~str,
    query : Vec<(~str,Vec<~str>)>,
}

impl Path {
    fn new() -> Path {
        Path { path : ~"", query : Vec::new() }
    }
}

fn parse_path(path : &str) -> Path {
    let mut result = Path::new();

    let v : ~[&str] = path.splitn('?', 2).collect();
    if v.len() == 0 {
        return result;
    }
    if v.len() == 1 {
        result.path = v[0].into_owned();
    }
    for attr in v[1].split('&') {
        let a : ~[&str] = attr.splitn('=', 2).collect();
        if a.len() == 2 {
            result.query.push((a[0].into_owned(),
                               a[1].split('+').map(|s| {s.into_owned() }).collect()));
        }
    }
    return result;
}

impl WebSession::Server for WebSessionImpl {
    fn get(&mut self, mut context : WebSession::GetContext) {
        println!("GET");
        let (params, results) = context.get();
        let raw_path = params.get_path();
        println!("path = {}", raw_path);
        let content = results.init_content();
        content.set_mime_type("text/html");

        let path = parse_path(raw_path);
        if raw_path == "main.css" {
            content.get_body().set_bytes(main_css.as_bytes())
        } else if path.path.as_slice() == "define" {
            content.get_body().set_bytes("AWESOME".as_bytes());
        } else {
            content.get_body().set_bytes(
                html_body(
                    "<form action=\"define\" method=\"get\">
                     <input name=\"word\"/><button>go</button></form>").as_bytes());
        }
        context.done()
    }
    fn post(&mut self, context : WebSession::PostContext) {
        println!("POST");
        context.done()
    }
    fn put(&mut self, context : WebSession::PutContext) {
        println!("PUT");
        context.done()
    }
    fn delete(&mut self, context : WebSession::DeleteContext) {
        println!("DELETE");
        context.done()
    }
    fn open_web_socket(&mut self, context : WebSession::OpenWebSocketContext) {
        println!("OPEN WEB SOCKET");
        context.done()
    }
}

pub struct FdStream {
    inner : ~::std::rt::rtio::RtioFileStream:Send,
}

impl FdStream {
    pub fn new(fd : ::libc::c_int) -> ::std::io::IoResult<FdStream> {
        ::std::rt::rtio::LocalIo::maybe_raise(|io| {
            Ok (FdStream { inner : io.fs_from_raw_fd(fd, ::std::rt::rtio::DontClose) })
        })
    }
}

impl Reader for FdStream {
    fn read(&mut self, buf : &mut [u8]) -> ::std::io::IoResult<uint> {
        self.inner.read(buf).map(|i| i as uint)
    }
}

impl Writer for FdStream {
    fn write(&mut self, buf : &[u8]) -> ::std::io::IoResult<()> {
        self.inner.write(buf)
    }
}

pub struct Restorer;

impl SturdyRefRestorer for Restorer {
    fn restore(&self, obj_id : AnyPointer::Reader) -> Option<~ClientHook:Send> {
        if obj_id.is_null() {
            let client : UiView::Client = FromServer::new(None::<LocalClient>, ~UiViewImpl);
            Some(client.client.hook)
        } else {
            None
        }
    }
}

pub fn main() -> ::std::io::IoResult<()> {
    let ifs = try!(FdStream::new(3));
    let ofs = try!(FdStream::new(3));

    let connection_state = RpcConnectionState::new();
    connection_state.run(ifs, ofs, Restorer);

    Ok(())
}

<commit_msg>fix control flow<commit_after>use grain_capnp::{PowerboxCapability, UiView, UiSession};
use web_session_capnp::{WebSession};

use capnp::capability::{ClientHook, FromServer};
use capnp::AnyPointer;
use capnp_rpc::rpc::{RpcConnectionState, SturdyRefRestorer};
use capnp_rpc::capability::{LocalClient};

pub struct UiViewImpl;

impl PowerboxCapability::Server for UiViewImpl {
    fn get_powerbox_info(&mut self, context : PowerboxCapability::GetPowerboxInfoContext) {
        context.done()
    }
}

impl UiView::Server for UiViewImpl {
    fn get_view_info(&mut self, context : UiView::GetViewInfoContext) {
        context.done()
    }

    fn new_session(&mut self, mut context : UiView::NewSessionContext) {
        println!("asked for a new session!");
        let (_, results) = context.get();

        let client : WebSession::Client = FromServer::new(None::<LocalClient>, ~WebSessionImpl);
        // we need to do this dance to upcast.
        results.set_session(UiSession::Client { client : client.client});

        context.done()
    }
}

pub struct WebSessionImpl;

impl UiSession::Server for WebSessionImpl {

}

static main_css : &'static str =
    "body { font-family: Helvetica, Sans, Arial;
            font-size: medium;
             margin-left: auto;
             margin-right: auto;
             width: 600px;
     }";

static header : &'static str =
  r#"<title> acronymy </title><link rel="stylesheet" type="text/css" href="main.css" >
 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
  "#;

fn html_body(body :&str) -> ~str {
    format!("{}{}", header, body)
}

struct Path {
    path : ~str,
    query : Vec<(~str,Vec<~str>)>,
}

impl Path {
    fn new() -> Path {
        Path { path : ~"", query : Vec::new() }
    }
}

fn parse_path(path : &str) -> Path {
    let mut result = Path::new();

    let v : ~[&str] = path.splitn('?', 2).collect();
    if v.len() == 0 {
        return result;
    }
    if v.len() == 1 {
        result.path = v[0].into_owned();
        return result;
    }
    for attr in v[1].split('&') {
        let a : ~[&str] = attr.splitn('=', 2).collect();
        if a.len() == 2 {
            result.query.push((a[0].into_owned(),
                               a[1].split('+').map(|s| {s.into_owned() }).collect()));
        }
    }
    return result;
}

impl WebSession::Server for WebSessionImpl {
    fn get(&mut self, mut context : WebSession::GetContext) {
        println!("GET");
        let (params, results) = context.get();
        let raw_path = params.get_path();
        println!("path = {}", raw_path);
        let content = results.init_content();
        content.set_mime_type("text/html");

        let path = parse_path(raw_path);
        if raw_path == "main.css" {
            content.get_body().set_bytes(main_css.as_bytes())
        } else if path.path.as_slice() == "define" {
            content.get_body().set_bytes("AWESOME".as_bytes());
        } else {
            content.get_body().set_bytes(
                html_body(
                    "<form action=\"define\" method=\"get\">
                     <input name=\"word\"/><button>go</button></form>").as_bytes());
        }
        context.done()
    }
    fn post(&mut self, context : WebSession::PostContext) {
        println!("POST");
        context.done()
    }
    fn put(&mut self, context : WebSession::PutContext) {
        println!("PUT");
        context.done()
    }
    fn delete(&mut self, context : WebSession::DeleteContext) {
        println!("DELETE");
        context.done()
    }
    fn open_web_socket(&mut self, context : WebSession::OpenWebSocketContext) {
        println!("OPEN WEB SOCKET");
        context.done()
    }
}

pub struct FdStream {
    inner : ~::std::rt::rtio::RtioFileStream:Send,
}

impl FdStream {
    pub fn new(fd : ::libc::c_int) -> ::std::io::IoResult<FdStream> {
        ::std::rt::rtio::LocalIo::maybe_raise(|io| {
            Ok (FdStream { inner : io.fs_from_raw_fd(fd, ::std::rt::rtio::DontClose) })
        })
    }
}

impl Reader for FdStream {
    fn read(&mut self, buf : &mut [u8]) -> ::std::io::IoResult<uint> {
        self.inner.read(buf).map(|i| i as uint)
    }
}

impl Writer for FdStream {
    fn write(&mut self, buf : &[u8]) -> ::std::io::IoResult<()> {
        self.inner.write(buf)
    }
}

pub struct Restorer;

impl SturdyRefRestorer for Restorer {
    fn restore(&self, obj_id : AnyPointer::Reader) -> Option<~ClientHook:Send> {
        if obj_id.is_null() {
            let client : UiView::Client = FromServer::new(None::<LocalClient>, ~UiViewImpl);
            Some(client.client.hook)
        } else {
            None
        }
    }
}

pub fn main() -> ::std::io::IoResult<()> {
    let ifs = try!(FdStream::new(3));
    let ofs = try!(FdStream::new(3));

    let connection_state = RpcConnectionState::new();
    connection_state.run(ifs, ofs, Restorer);

    Ok(())
}

<|endoftext|>


<commit_before>
use std::num::{One, Zero};
use std::fmt;
use std::rand;
use math;

#[deriving(Clone, Show)]
/// Signal generic struct for simplifying dsp signal generation.
pub struct Signal<F> {
    pub val: F,
    x: F,
    y: F,
    grad: F,
    pub bez_depth: F,
    pub freq: F,
    pub amp: F
}

/// Times two pi for most methods in 'Signal' implementations.
fn times_two_pi<F: FloatMath>(f: F) -> F { f * Float::two_pi() }

/// Get random() mapped from -1.0 to 1.0 for 'Signal::get_noise'.
fn get_rand_signal<F: FloatMath + rand::Rand + FromPrimitive>() -> F {
    let r: F = rand::random();
    r * FromPrimitive::from_f32(2.0f32).unwrap() - FromPrimitive::from_f32(1.0f32).unwrap()
}

impl<F: FloatMath + rand::Rand + FromPrimitive + ToPrimitive + Signed> Signal<F> {

    /// Constructor for Signal
    pub fn new(val: F) -> Signal<F> {
        Signal {
            val: val,
            x: One::one(),
            y: Zero::zero(),
            grad: Zero::zero(),
            bez_depth: Zero::zero(),
            freq: One::one(),
            amp: One::one()
        }
    }

    /// Set value for which you will return signal (get_sin/cos/sqr/saw) etc...
    pub fn set_val(&mut self, val: F) {
        self.val = val;
    }

    /// If you woudl like to return the signal value on a slope, set gradient here.
    pub fn set_gradient(&mut self, x: F, y: F) {
        self.x = x;
        self.y = y;
        self.grad = x / y;
    }

    /// Set frequency of signal.
    pub fn set_freq(&mut self, freq: F) {
        self.freq = freq;
    }

    /// Set amplitude of signal.
    pub fn set_amp(&mut self, amp: F) {
        self.amp = amp;
    }

    /// Set depth of bezier curve. Defaults to 0.
    pub fn set_bez_depth(&mut self, bez_depth: F) {
        self.bez_depth = bez_depth;
    }

    /// Helper function for 'get_bezier'.
    fn get_bezier_pt(na: F, nb: F, perc: F) -> F {
        let diff: F = nb - na;
        diff * perc + na
    }

    /// Helper function for 'get_bezier'.
    fn get_y1(y: F, one: F) -> F {
        y/(one+one)
    }

    /// Get signal with bezier curve.
    pub fn get_bezier(&self) -> F {
        let y1: F = Signal::get_y1(self.y, One::one());
        let y2: F = y1 + self.bez_depth * y1;
        let relative_val: F = self.val / self.x;
        let ya: F = Signal::get_bezier_pt(Zero::zero(), y2, relative_val);
        let yb: F = Signal::get_bezier_pt(y2, self.y, relative_val);
        Signal::get_bezier_pt(ya, yb, relative_val)
    }

    /// Get oscillator with amplitude and bezier.
    pub fn get_result(&self, val: F) -> F {
        self.amp * val + self.get_bezier()
    }

    /// Get sine wave signal result at val.
    pub fn get_sin(&self) -> F {
        self.get_result((times_two_pi(self.val) * self.freq / self.x).sin())
    }

    /// Get cosine wave signal result at val.
    pub fn get_cos(&self) -> F {
        self.get_result((times_two_pi(self.val) * self.freq / self.x).cos())
    }

    /// Get saw wave signal result at val.
    pub fn get_saw(&self) -> F {
        self.get_result(((self.val * self.freq / self.x) % One::one()) * FromPrimitive::from_int(-2).unwrap() + FromPrimitive::from_int(1).unwrap())
    }

    /// Get square wave signal result at val.
    pub fn get_sqr(&self) -> F {
        self.get_result((times_two_pi(self.val) * self.freq / self.x).sin().signum())
    }

    /// Get noise signal result at val.
    pub fn get_noise(&self) -> F {
        self.get_result(get_rand_signal())
    }

    /// Ported implementation of _slang_library_noise1()
    pub fn get_noise_walk(&self) -> F {
        let uno: F = One::one();
        let i0: int = jmath::fast_floor(self.val);
        let i1: int = i0 + 1;
        let x0: F = self.val - FromPrimitive::from_int(i0).unwrap();
        let x1: F = x0 - uno;
        let x12d: F = x1 * x1;
        let x02d: F = x0 * x0;
        let t1: F = uno - x12d;
        let t0: F = uno - x02d;
        let t0a: F = t0 * t0;
        let g1: f32 = jmath::grad1(jmath::get_perm_val((i0 & 0xff) as uint) as int, x0.to_f32().unwrap());
        let n0: F = t0a * t0a * FromPrimitive::from_f32(g1).unwrap();
        let t1a: F = t1 * t1;
        let g2: f32 = jmath::grad1(jmath::get_perm_val((i1 & 0xff) as uint) as int, x1.to_f32().unwrap());
        let n1: F = t1a * t1a * FromPrimitive::from_f32(g2).unwrap();
        let n0pn1: F = n0 + n1;
        let quarter: F = FromPrimitive::from_f32(0.25f32).unwrap();
        quarter * n0pn1
    }

}

// Tests
//------------------------------

/*
fn print<F: FloatMath + fmt::Show>(b: Signal<F>) {
    println!("{}", b);
}

pub fn test() {
    println!("Signal struct 'new' test.");
    let mut a = Signal::new(0.0f32);

    print(a.clone());

    println!("Testing sin");
    for i in range (0.0f32, 20.0f32) {
        a.set_val(jmath::map(i, 0.0f32, 20.0f32, 0.0f32, 1.0f32));
        print!("{}, ", a.get_sin());
    }
    println!("");

    println!("Testing cos");
    for i in range (0.0f32, 20.0f32) {
        a.set_val(jmath::map(i, 0.0f32, 20.0f32, 0.0f32, 1.0f32));
        print!("{}, ", a.get_cos());
    }
    println!("");

    println!("Testing get_rand");
    for i in range (0.0f32, 20.0f32) {
        a.set_val(jmath::map(i, 0.0f32, 20.0f32, 0.0f32, 1.0f32));
        print!("{}, ", a.get_noise());
    }
    println!("");

    println!("Testing get_sqr");
    for i in range (0.0f32, 20.0f32) {
        a.set_val(jmath::map(i, 0.0f32, 20.0f32, 0.0f32, 1.0f32));
        print!("{}, ", a.get_sqr());
    }
    println!("");

    println!("Testing get_saw");
    for i in range (0.0f32, 20.0f32) {
        a.set_val(jmath::map(i, 0.0f32, 20.0f32, 0.0f32, 1.0f32));
        print!("{}, ", a.get_saw());
    }
    println!("");

    println!("Testing get_noise_walk");
    for i in range (0.0f32, 20.0f32) {
        a.set_val(jmath::map(i, 0.0f32, 20.0f32, 0.0f32, 1.0f32));
        print!("{}, ", a.get_noise_walk());
    }
    //loop { println!("{}", a.get_noise_walk()); a.set_val(a.val + 0.001f32); }
    println!("");

    println!("Testing set_gradient.");
    a.set_gradient(3.0f32, 1.25f32);
    println!("New gradient = x: {}, y: {}, grad: {}", a.x, a.y, a.grad);
    println!("Testing setters.");
    a.set_freq(20.0f32);
    a.set_amp(0.85f32);
    a.set_bez_depth(0.5f32);
    print(a.clone());
}
*/
//------------------------------
<commit_msg>Added Signal struct, a helper struct for generating basic signals<commit_after>
use std::num::{One, Zero};
use std::fmt;
use std::rand;
use math;

/// Signal generic struct for simplifying dsp signal generation.
/// Signal should be able to handle any floating point primitive.
#[deriving(Clone, Show)]
pub struct Signal<F> {
    /// The main value. If Signal were to be plotted on a cartesian
    /// plane, this value would be 'x' for which we will solve 'y'.
    pub val: F,
    /// Optional: The 'x' value of the second point
    /// (from which we calc our range and gradient)
    x: F,
    /// Optional: The 'y' value of the second point
    /// (from which we calc our range and gradient)
    y: F,
    /// The calculated gradient.
    grad: F,
    /// Depth of the bezier curve.
    pub bez_depth: F,
    /// Frequency of the signal.
    pub freq: F,
    /// Amplitude of the signal.
    pub amp: F
}

/// Times two pi for most methods in 'Signal' implementations.
fn times_two_pi<F: FloatMath>(f: F) -> F { f * Float::two_pi() }

/// Get random() mapped from -1.0 to 1.0 for 'Signal::get_noise'.
fn get_rand_signal<F: FloatMath + rand::Rand + FromPrimitive>() -> F {
    let r: F = rand::random();
    r * FromPrimitive::from_f32(2.0f32).unwrap() - FromPrimitive::from_f32(1.0f32).unwrap()
}

impl<F: FloatMath + rand::Rand + FromPrimitive + ToPrimitive + Signed> Signal<F> {

    /// Constructor for Signal
    pub fn new(val: F) -> Signal<F> {
        Signal {
            val: val,
            x: One::one(),
            y: Zero::zero(),
            grad: Zero::zero(),
            bez_depth: Zero::zero(),
            freq: One::one(),
            amp: One::one()
        }
    }

    /// Set value for which you will return signal (get_sin/cos/sqr/saw) etc...
    pub fn set_val(&mut self, val: F) {
        self.val = val;
    }

    /// If you woudl like to return the signal value on a slope, set gradient here.
    pub fn set_gradient(&mut self, x: F, y: F) {
        self.x = x;
        self.y = y;
        self.grad = x / y;
    }

    /// Set frequency of signal.
    pub fn set_freq(&mut self, freq: F) {
        self.freq = freq;
    }

    /// Set amplitude of signal.
    pub fn set_amp(&mut self, amp: F) {
        self.amp = amp;
    }

    /// Set depth of bezier curve. Defaults to 0.
    pub fn set_bez_depth(&mut self, bez_depth: F) {
        self.bez_depth = bez_depth;
    }

    /// Helper function for 'get_bezier'.
    fn get_bezier_pt(na: F, nb: F, perc: F) -> F {
        let diff: F = nb - na;
        diff * perc + na
    }

    /// Helper function for 'get_bezier'.
    fn get_y1(y: F, one: F) -> F {
        y/(one+one)
    }

    /// Get signal with bezier curve.
    pub fn get_bezier(&self) -> F {
        let y1: F = Signal::get_y1(self.y, One::one());
        let y2: F = y1 + self.bez_depth * y1;
        let relative_val: F = self.val / self.x;
        let ya: F = Signal::get_bezier_pt(Zero::zero(), y2, relative_val);
        let yb: F = Signal::get_bezier_pt(y2, self.y, relative_val);
        Signal::get_bezier_pt(ya, yb, relative_val)
    }

    /// Get oscillator with amplitude and bezier.
    pub fn get_result(&self, val: F) -> F {
        self.amp * val + self.get_bezier()
    }

    /// Get sine wave signal result at val.
    pub fn get_sin(&self) -> F {
        self.get_result((times_two_pi(self.val) * self.freq / self.x).sin())
    }

    /// Get cosine wave signal result at val.
    pub fn get_cos(&self) -> F {
        self.get_result((times_two_pi(self.val) * self.freq / self.x).cos())
    }

    /// Get saw wave signal result at val.
    pub fn get_saw(&self) -> F {
        self.get_result(((self.val * self.freq / self.x) % One::one()) * FromPrimitive::from_int(-2).unwrap() + FromPrimitive::from_int(1).unwrap())
    }

    /// Get square wave signal result at val.
    pub fn get_sqr(&self) -> F {
        self.get_result((times_two_pi(self.val) * self.freq / self.x).sin().signum())
    }

    /// Get noise signal result at val.
    pub fn get_noise(&self) -> F {
        self.get_result(get_rand_signal())
    }

    /// Ported implementation of `_slang_library_noise1()`
    /// for our generic noise walk!
    pub fn get_noise_walk(&self) -> F {
        let uno: F = One::one();
        let i0: int = math::fast_floor(self.val);
        let i1: int = i0 + 1;
        let x0: F = self.val - FromPrimitive::from_int(i0).unwrap();
        let x1: F = x0 - uno;
        let x12d: F = x1 * x1;
        let x02d: F = x0 * x0;
        let t1: F = uno - x12d;
        let t0: F = uno - x02d;
        let t0a: F = t0 * t0;
        let g1: f32 = math::grad1(
            math::get_perm_val((i0 & 0xff) as uint) as int, x0.to_f32().unwrap());
        let n0: F = t0a * t0a * FromPrimitive::from_f32(g1).unwrap();
        let t1a: F = t1 * t1;
        let g2: f32 = math::grad1(
            math::get_perm_val((i1 & 0xff) as uint) as int, x1.to_f32().unwrap());
        let n1: F = t1a * t1a * FromPrimitive::from_f32(g2).unwrap();
        let n0pn1: F = n0 + n1;
        let quarter: F = FromPrimitive::from_f32(0.25f32).unwrap();
        quarter * n0pn1
    }

}

// Tests
//------------------------------

/*
fn print<F: FloatMath + fmt::Show>(b: Signal<F>) {
    println!("{}", b);
}

pub fn test() {
    println!("Signal struct 'new' test.");
    let mut a = Signal::new(0.0f32);

    print(a.clone());

    println!("Testing sin");
    for i in range (0.0f32, 20.0f32) {
        a.set_val(math::map(i, 0.0f32, 20.0f32, 0.0f32, 1.0f32));
        print!("{}, ", a.get_sin());
    }
    println!("");

    println!("Testing cos");
    for i in range (0.0f32, 20.0f32) {
        a.set_val(math::map(i, 0.0f32, 20.0f32, 0.0f32, 1.0f32));
        print!("{}, ", a.get_cos());
    }
    println!("");

    println!("Testing get_rand");
    for i in range (0.0f32, 20.0f32) {
        a.set_val(math::map(i, 0.0f32, 20.0f32, 0.0f32, 1.0f32));
        print!("{}, ", a.get_noise());
    }
    println!("");

    println!("Testing get_sqr");
    for i in range (0.0f32, 20.0f32) {
        a.set_val(math::map(i, 0.0f32, 20.0f32, 0.0f32, 1.0f32));
        print!("{}, ", a.get_sqr());
    }
    println!("");

    println!("Testing get_saw");
    for i in range (0.0f32, 20.0f32) {
        a.set_val(math::map(i, 0.0f32, 20.0f32, 0.0f32, 1.0f32));
        print!("{}, ", a.get_saw());
    }
    println!("");

    println!("Testing get_noise_walk");
    for i in range (0.0f32, 20.0f32) {
        a.set_val(math::map(i, 0.0f32, 20.0f32, 0.0f32, 1.0f32));
        print!("{}, ", a.get_noise_walk());
    }
    //loop { println!("{}", a.get_noise_walk()); a.set_val(a.val + 0.001f32); }
    println!("");

    println!("Testing set_gradient.");
    a.set_gradient(3.0f32, 1.25f32);
    println!("New gradient = x: {}, y: {}, grad: {}", a.x, a.y, a.grad);
    println!("Testing setters.");
    a.set_freq(20.0f32);
    a.set_amp(0.85f32);
    a.set_bez_depth(0.5f32);
    print(a.clone());
}
*/
//------------------------------
<|endoftext|>


<commit_before>use std::io;
use std::io::ErrorKind::WouldBlock;
use std::net::SocketAddr;

use mio::tcp::TcpStream;
#[cfg(feature="ssl")]
use openssl::ssl::SslStream;
#[cfg(feature="ssl")]
use openssl::ssl::error::Error as SslError;
use bytes::Buf;

use result::{Result, Error, Kind};

fn map_non_block<T>(res: io::Result<T>) -> io::Result<Option<T>> {
    match res {
        Ok(value) => Ok(Some(value)),
        Err(err) => {
            if let WouldBlock = err.kind() {
                Ok(None)
            } else {
                Err(err)
            }
        }
    }
}

pub trait TryReadBuf: io::Read {
    fn try_read_buf(&mut self, buf: &mut Vec<u8>) -> io::Result<Option<usize>>
        where Self : Sized
    {
        // Reads the length of the slice supplied by buf into the buffer
        // This is not guaranteed to consume an entire datagram or segment.
        // If your protocol is msg based (instead of continuous stream) you should
        // ensure that your buffer is large enough to hold an entire segment (1532 bytes if not jumbo
        // frames)
        map_non_block(self.read_to_end(buf))
    }
}

pub trait TryWriteBuf: io::Write {
    fn try_write_buf<B: Buf>(&mut self, buf: &mut B) -> io::Result<Option<usize>>
        where Self : Sized
    {
        let res = map_non_block(self.write(buf.bytes()));

        if let Ok(Some(cnt)) = res {
            buf.advance(cnt);
        }

        res
    }
}

impl<T: io::Read> TryReadBuf for T {}
impl<T: io::Write> TryWriteBuf for T {}

use self::Stream::*;
pub enum Stream {
    Tcp(TcpStream),
    #[cfg(feature="ssl")]
    Tls {
        sock: SslStream<TcpStream>,
        negotiating: bool,
    }
}

impl Stream {

    pub fn tcp(stream: TcpStream) -> Stream {
        Tcp(stream)
    }

    #[cfg(feature="ssl")]
    pub fn tls(stream: SslStream<TcpStream>) -> Stream {
        Tls { sock: stream, negotiating: false }
    }

    #[cfg(feature="ssl")]
    pub fn is_tls(&self) -> bool {
        match *self {
            Tcp(_) => false,
            Tls {..} => true,
        }
    }

    pub fn evented(&self) -> &TcpStream {
        match *self {
            Tcp(ref sock) => sock,
            #[cfg(feature="ssl")]
            Tls { ref sock, ..} => sock.get_ref(),
        }
    }

    pub fn is_negotiating(&self) -> bool {
        match *self {
            Tcp(_) => false,
            #[cfg(feature="ssl")]
            Tls { sock: _, ref negotiating } => *negotiating,
        }

    }

    pub fn clear_negotiating(&mut self) -> Result<()> {
        match *self {
            Tcp(_) => Err(Error::new(Kind::Internal, "Attempted to clear negotiating flag on non ssl connection.")),
            #[cfg(feature="ssl")]
            Tls { sock: _, ref mut negotiating } => Ok(*negotiating = false),
        }
    }

    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
        match *self {
            Tcp(ref sock) => sock.peer_addr(),
            #[cfg(feature="ssl")]
            Tls { ref sock, ..} => sock.get_ref().peer_addr(),
        }
    }

    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        match *self {
            Tcp(ref sock) => sock.local_addr(),
            #[cfg(feature="ssl")]
            Tls { ref sock, ..} => sock.get_ref().local_addr(),
        }
    }
}

impl io::Read for Stream {

    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match *self {
            Tcp(ref mut sock) => sock.read(buf),
            #[cfg(feature="ssl")]
            Tls { ref mut sock, ref mut negotiating } => {
                match sock.ssl_read(buf) {
                    Ok(cnt) => Ok(cnt),
                    Err(SslError::WantWrite(_)) => {
                        *negotiating = true;
                        Err(io::Error::new(io::ErrorKind::WouldBlock, "SSL wants writing"))
                    },
                    Err(SslError::WantRead(_)) => Err(io::Error::new(io::ErrorKind::WouldBlock, "SSL wants reading")),
                    Err(err) =>
                        Err(io::Error::new(io::ErrorKind::Other, err)),
                }
            }
        }
    }
}

impl io::Write for Stream {

    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match *self {
            Tcp(ref mut sock) => sock.write(buf),
            #[cfg(feature="ssl")]
            Tls { ref mut sock, ref mut negotiating } => {

                *negotiating = false;

                match sock.ssl_write(buf) {
                    Ok(cnt) => Ok(cnt),
                    Err(SslError::WantRead(_)) => {
                        *negotiating = true;
                        Err(io::Error::new(io::ErrorKind::WouldBlock, "SSL wants reading"))
                    },
                    Err(SslError::WantWrite(_)) => Err(io::Error::new(io::ErrorKind::WouldBlock, "SSL wants writing")),
                    Err(err) =>
                        Err(io::Error::new(io::ErrorKind::Other, err)),
                }
            }
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match *self {
            Tcp(ref mut sock) => sock.flush(),
            #[cfg(feature="ssl")]
            Tls { ref mut sock, negotiating: _ } => sock.flush(),
        }
    }
}
<commit_msg>Revert "refactor(stream): Change TryReadBuf to take Vec directly instead of BufMut"<commit_after>use std::io;
use std::io::ErrorKind::WouldBlock;
use std::net::SocketAddr;

use mio::tcp::TcpStream;
#[cfg(feature="ssl")]
use openssl::ssl::SslStream;
#[cfg(feature="ssl")]
use openssl::ssl::error::Error as SslError;
use bytes::{Buf, BufMut};

use result::{Result, Error, Kind};

fn map_non_block<T>(res: io::Result<T>) -> io::Result<Option<T>> {
    match res {
        Ok(value) => Ok(Some(value)),
        Err(err) => {
            if let WouldBlock = err.kind() {
                Ok(None)
            } else {
                Err(err)
            }
        }
    }
}

pub trait TryReadBuf: io::Read {
    fn try_read_buf<B: BufMut>(&mut self, buf: &mut B) -> io::Result<Option<usize>>
        where Self : Sized
    {
        // Reads the length of the slice supplied by buf.mut_bytes into the buffer
        // This is not guaranteed to consume an entire datagram or segment.
        // If your protocol is msg based (instead of continuous stream) you should
        // ensure that your buffer is large enough to hold an entire segment (1532 bytes if not jumbo
        // frames)
        let res = map_non_block(self.read(unsafe { buf.bytes_mut() }));

        if let Ok(Some(cnt)) = res {
            unsafe { buf.advance_mut(cnt); }
        }

        res
    }
}

pub trait TryWriteBuf: io::Write {
    fn try_write_buf<B: Buf>(&mut self, buf: &mut B) -> io::Result<Option<usize>>
        where Self : Sized
    {
        let res = map_non_block(self.write(buf.bytes()));

        if let Ok(Some(cnt)) = res {
            buf.advance(cnt);
        }

        res
    }
}

impl<T: io::Read> TryReadBuf for T {}
impl<T: io::Write> TryWriteBuf for T {}

use self::Stream::*;
pub enum Stream {
    Tcp(TcpStream),
    #[cfg(feature="ssl")]
    Tls {
        sock: SslStream<TcpStream>,
        negotiating: bool,
    }
}

impl Stream {

    pub fn tcp(stream: TcpStream) -> Stream {
        Tcp(stream)
    }

    #[cfg(feature="ssl")]
    pub fn tls(stream: SslStream<TcpStream>) -> Stream {
        Tls { sock: stream, negotiating: false }
    }

    #[cfg(feature="ssl")]
    pub fn is_tls(&self) -> bool {
        match *self {
            Tcp(_) => false,
            Tls {..} => true,
        }
    }

    pub fn evented(&self) -> &TcpStream {
        match *self {
            Tcp(ref sock) => sock,
            #[cfg(feature="ssl")]
            Tls { ref sock, ..} => sock.get_ref(),
        }
    }

    pub fn is_negotiating(&self) -> bool {
        match *self {
            Tcp(_) => false,
            #[cfg(feature="ssl")]
            Tls { sock: _, ref negotiating } => *negotiating,
        }

    }

    pub fn clear_negotiating(&mut self) -> Result<()> {
        match *self {
            Tcp(_) => Err(Error::new(Kind::Internal, "Attempted to clear negotiating flag on non ssl connection.")),
            #[cfg(feature="ssl")]
            Tls { sock: _, ref mut negotiating } => Ok(*negotiating = false),
        }
    }

    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
        match *self {
            Tcp(ref sock) => sock.peer_addr(),
            #[cfg(feature="ssl")]
            Tls { ref sock, ..} => sock.get_ref().peer_addr(),
        }
    }

    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        match *self {
            Tcp(ref sock) => sock.local_addr(),
            #[cfg(feature="ssl")]
            Tls { ref sock, ..} => sock.get_ref().local_addr(),
        }
    }
}

impl io::Read for Stream {

    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match *self {
            Tcp(ref mut sock) => sock.read(buf),
            #[cfg(feature="ssl")]
            Tls { ref mut sock, ref mut negotiating } => {
                match sock.ssl_read(buf) {
                    Ok(cnt) => Ok(cnt),
                    Err(SslError::WantWrite(_)) => {
                        *negotiating = true;
                        Err(io::Error::new(io::ErrorKind::WouldBlock, "SSL wants writing"))
                    },
                    Err(SslError::WantRead(_)) => Err(io::Error::new(io::ErrorKind::WouldBlock, "SSL wants reading")),
                    Err(err) =>
                        Err(io::Error::new(io::ErrorKind::Other, err)),
                }
            }
        }
    }
}

impl io::Write for Stream {

    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match *self {
            Tcp(ref mut sock) => sock.write(buf),
            #[cfg(feature="ssl")]
            Tls { ref mut sock, ref mut negotiating } => {

                *negotiating = false;

                match sock.ssl_write(buf) {
                    Ok(cnt) => Ok(cnt),
                    Err(SslError::WantRead(_)) => {
                        *negotiating = true;
                        Err(io::Error::new(io::ErrorKind::WouldBlock, "SSL wants reading"))
                    },
                    Err(SslError::WantWrite(_)) => Err(io::Error::new(io::ErrorKind::WouldBlock, "SSL wants writing")),
                    Err(err) =>
                        Err(io::Error::new(io::ErrorKind::Other, err)),
                }
            }
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match *self {
            Tcp(ref mut sock) => sock.flush(),
            #[cfg(feature="ssl")]
            Tls { ref mut sock, negotiating: _ } => sock.flush(),
        }
    }
}
<|endoftext|>


<commit_before>//! Manager that is called when an output is created or destroyed.
//! Pass a struct that implements this trait to the `Compositor` during
//! initialization.

use Output;
use compositor::{Compositor, COMPOSITOR_PTR};
use errors::UpgradeHandleErr;
use libc;
use manager::{OutputHandler, UserOutput};

use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::wlr_output;

use std::panic;

/// Used to ensure the output sets the mode before doing any other
/// operation on the Output.
pub struct OutputBuilder<'output> {
    output: &'output mut Output
}

/// Used to ensure that the builder is used to construct
/// the OutputHandler instance.
pub struct OutputBuilderResult<'output> {
    pub output: &'output mut Output,
    result: Box<OutputHandler>
}

/// Wrapper around Output destruction so that you can't call
/// unsafe methods (e.g anything like setting the mode).
pub struct OutputDestruction<'output>(&'output mut Output);

/// Handles output addition and removal.
pub trait OutputManagerHandler {
    /// Called whenever an output is added.
    ///
    /// # Panics
    /// Any panic in this function will cause the process to abort.
    fn output_added<'output>(&mut self,
                             &mut Compositor,
                             _: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        None
    }

    /// Called whenever an output is removed.
    fn output_removed(&mut self, &mut Compositor, OutputDestruction) {
        // TODO
    }
}

impl<'output> OutputBuilder<'output> {
    pub fn build_best_mode<T: OutputHandler + 'static>(self,
                                                       data: T)
                                                       -> OutputBuilderResult<'output> {
        self.output.choose_best_mode();
        OutputBuilderResult { output: self.output,
                              result: Box::new(data) }
    }
}

impl<'output> OutputDestruction<'output> {
    // TODO Functions which are safe to use
}

wayland_listener!(OutputManager, (Vec<Box<UserOutput>>, Box<OutputManagerHandler>), [
    add_listener => add_notify: |this: &mut OutputManager, data: *mut libc::c_void,| unsafe {
        let remove_listener = this.remove_listener()  as *mut _ as _;
        let (ref mut outputs, ref mut manager) = this.data;
        let data = data as *mut wlr_output;
        let mut output = Output::new(data as *mut wlr_output);
        // NOTE
        // This clone is required because we pass it mutably to the output builder,
        // but due to lack of NLL there's no way to tell Rust it's safe to use it in
        // in the if branch.
        //
        // Thus, we need to clone it here and then drop the original once at the end.
        //
        // This is not a real clone, but an pub(crate) unsafe one we added, so it doesn't
        // break safety concerns in user code. Just an unfortunate hack we have to put here.
        let output_clone = output.clone();
        let builder = OutputBuilder { output: &mut output };
        let compositor = &mut *COMPOSITOR_PTR;
        output_clone.set_lock(true);
        let res = panic::catch_unwind(
            panic::AssertUnwindSafe(||manager.output_added(compositor, builder)));
        let build_result = match res {
            Ok(res) => res,
            // NOTE
            // Either Wayland or wlroots does not handle failure to set up output correctly.
            // Calling wl_display_terminate does not work if output is incorrectly set up.
            //
            // Instead, execution keeps going with an eventual segfault (if lucky).
            //
            // To fix this, we abort the process if there was a panic in output setup.
            Err(_) => ::std::process::abort()
        };
        if let Some(OutputBuilderResult {result: output_ptr, .. }) = build_result {
            output_clone.set_lock(false);
            let mut output = UserOutput::new((output_clone, output_ptr));
            // Add the output frame event to this manager
            wl_signal_add(&mut (*data).events.frame as *mut _ as _,
                          output.frame_listener() as _);
            // Add the output mode event to this manager
            wl_signal_add(&mut (*data).events.mode as *mut _ as _,
                          output.mode_listener() as _);
            // Add the output enable event to this manager
            wl_signal_add(&mut (*data).events.enable as *mut _ as _,
                          output.enable_listener() as _);
            // Add the output scale change event to this manager
            wl_signal_add(&mut (*data).events.scale as *mut _ as _,
                          output.scale_listener() as _);
            // Add the output transform event to this manager
            wl_signal_add(&mut (*data).events.transform as *mut _ as _,
                          output.transform_listener() as _);
            // Add the output buffer swap event to this manager
            wl_signal_add(&mut (*data).events.swap_buffers as *mut _ as _,
                          output.swap_buffers_listener() as _);
            // Add the output need swap event to this manager
            wl_signal_add(&mut (*data).events.needs_swap as *mut _ as _,
                          output.need_swap_listener() as _);
            // Add the output destroy event to this manager
            wl_signal_add(&mut (*data).events.destroy as *mut _ as _,
                          remove_listener);
            // Store the user UserOutput, free later in remove listener
            outputs.push(output);
        }
    };
    remove_listener => remove_notify: |this: &mut OutputManager, data: *mut libc::c_void,| unsafe {
        let (ref mut outputs, ref mut manager) = this.data;
        let data = data as *mut wlr_output;
        if COMPOSITOR_PTR.is_null() {
            // We are shutting down, do nothing.
            return;
        }
        let compositor = &mut *COMPOSITOR_PTR;
        // NOTE
        // We get it from the list so that we can get the Rc'd `Output`, because there's
        // no way to re-construct that using just the raw pointer.
        if let Some(output) = outputs.iter_mut().find(|output| output.output_ptr() == data) {
            let output = output.output_mut();
            output.set_lock(true);
            manager.output_removed(compositor, OutputDestruction(output));
            // NOTE We don't remove the lock because we are removing it
            if let Some(mut layout) = output.layout() {
                match layout.run(|layout| layout.remove(output)) {
                    Ok(_) | Err(UpgradeHandleErr::AlreadyDropped) => {},
                    Err(UpgradeHandleErr::AlreadyBorrowed) => {
                        panic!("Tried to remove layout from output, but it's already borrowed");
                    }
                }
            }
        }
        // Remove user output data
        if let Some(index) = outputs.iter().position(|output| output.output_ptr() == data) {
            let mut removed_output = outputs.remove(index);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_output.frame_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_output.mode_listener()).link as *mut _ as _);
            // TODO Remove the rest of them
        }
    };
]);
<commit_msg>Added OutputBuilder::handle<commit_after>//! Manager that is called when an output is created or destroyed.
//! Pass a struct that implements this trait to the `Compositor` during
//! initialization.

use {Output, OutputHandle};
use compositor::{Compositor, COMPOSITOR_PTR};
use errors::UpgradeHandleErr;
use libc;
use manager::{OutputHandler, UserOutput};

use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::wlr_output;

use std::panic;

/// Used to ensure the output sets the mode before doing any other
/// operation on the Output.
pub struct OutputBuilder<'output> {
    output: &'output mut Output
}

/// Used to ensure that the builder is used to construct
/// the OutputHandler instance.
pub struct OutputBuilderResult<'output> {
    pub output: &'output mut Output,
    result: Box<OutputHandler>
}

/// Wrapper around Output destruction so that you can't call
/// unsafe methods (e.g anything like setting the mode).
pub struct OutputDestruction<'output>(&'output mut Output);

/// Handles output addition and removal.
pub trait OutputManagerHandler {
    /// Called whenever an output is added.
    ///
    /// # Panics
    /// Any panic in this function will cause the process to abort.
    fn output_added<'output>(&mut self,
                             &mut Compositor,
                             _: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        None
    }

    /// Called whenever an output is removed.
    fn output_removed(&mut self, &mut Compositor, OutputDestruction) {
        // TODO
    }
}

impl<'output> OutputBuilder<'output> {
    /// Get a handle to the output this is building.
    ///
    /// This is so you can use this output later.
    pub fn handle(&self) -> OutputHandle {
        self.output.weak_reference()
    }

    /// Build the output with the best mode.
    ///
    /// To complete construction, return this in your implementation of
    /// `OutputManagerHandler::output_added`.
    pub fn build_best_mode<T: OutputHandler + 'static>(self,
                                                       data: T)
                                                       -> OutputBuilderResult<'output> {
        self.output.choose_best_mode();
        OutputBuilderResult { output: self.output,
                              result: Box::new(data) }
    }
}

impl<'output> OutputDestruction<'output> {
    // TODO Functions which are safe to use
}

wayland_listener!(OutputManager, (Vec<Box<UserOutput>>, Box<OutputManagerHandler>), [
    add_listener => add_notify: |this: &mut OutputManager, data: *mut libc::c_void,| unsafe {
        let remove_listener = this.remove_listener()  as *mut _ as _;
        let (ref mut outputs, ref mut manager) = this.data;
        let data = data as *mut wlr_output;
        let mut output = Output::new(data as *mut wlr_output);
        // NOTE
        // This clone is required because we pass it mutably to the output builder,
        // but due to lack of NLL there's no way to tell Rust it's safe to use it in
        // in the if branch.
        //
        // Thus, we need to clone it here and then drop the original once at the end.
        //
        // This is not a real clone, but an pub(crate) unsafe one we added, so it doesn't
        // break safety concerns in user code. Just an unfortunate hack we have to put here.
        let output_clone = output.clone();
        let builder = OutputBuilder { output: &mut output };
        let compositor = &mut *COMPOSITOR_PTR;
        output_clone.set_lock(true);
        let res = panic::catch_unwind(
            panic::AssertUnwindSafe(||manager.output_added(compositor, builder)));
        let build_result = match res {
            Ok(res) => res,
            // NOTE
            // Either Wayland or wlroots does not handle failure to set up output correctly.
            // Calling wl_display_terminate does not work if output is incorrectly set up.
            //
            // Instead, execution keeps going with an eventual segfault (if lucky).
            //
            // To fix this, we abort the process if there was a panic in output setup.
            Err(_) => ::std::process::abort()
        };
        if let Some(OutputBuilderResult {result: output_ptr, .. }) = build_result {
            output_clone.set_lock(false);
            let mut output = UserOutput::new((output_clone, output_ptr));
            // Add the output frame event to this manager
            wl_signal_add(&mut (*data).events.frame as *mut _ as _,
                          output.frame_listener() as _);
            // Add the output mode event to this manager
            wl_signal_add(&mut (*data).events.mode as *mut _ as _,
                          output.mode_listener() as _);
            // Add the output enable event to this manager
            wl_signal_add(&mut (*data).events.enable as *mut _ as _,
                          output.enable_listener() as _);
            // Add the output scale change event to this manager
            wl_signal_add(&mut (*data).events.scale as *mut _ as _,
                          output.scale_listener() as _);
            // Add the output transform event to this manager
            wl_signal_add(&mut (*data).events.transform as *mut _ as _,
                          output.transform_listener() as _);
            // Add the output buffer swap event to this manager
            wl_signal_add(&mut (*data).events.swap_buffers as *mut _ as _,
                          output.swap_buffers_listener() as _);
            // Add the output need swap event to this manager
            wl_signal_add(&mut (*data).events.needs_swap as *mut _ as _,
                          output.need_swap_listener() as _);
            // Add the output destroy event to this manager
            wl_signal_add(&mut (*data).events.destroy as *mut _ as _,
                          remove_listener);
            // Store the user UserOutput, free later in remove listener
            outputs.push(output);
        }
    };
    remove_listener => remove_notify: |this: &mut OutputManager, data: *mut libc::c_void,| unsafe {
        let (ref mut outputs, ref mut manager) = this.data;
        let data = data as *mut wlr_output;
        if COMPOSITOR_PTR.is_null() {
            // We are shutting down, do nothing.
            return;
        }
        let compositor = &mut *COMPOSITOR_PTR;
        // NOTE
        // We get it from the list so that we can get the Rc'd `Output`, because there's
        // no way to re-construct that using just the raw pointer.
        if let Some(output) = outputs.iter_mut().find(|output| output.output_ptr() == data) {
            let output = output.output_mut();
            output.set_lock(true);
            manager.output_removed(compositor, OutputDestruction(output));
            // NOTE We don't remove the lock because we are removing it
            if let Some(mut layout) = output.layout() {
                match layout.run(|layout| layout.remove(output)) {
                    Ok(_) | Err(UpgradeHandleErr::AlreadyDropped) => {},
                    Err(UpgradeHandleErr::AlreadyBorrowed) => {
                        panic!("Tried to remove layout from output, but it's already borrowed");
                    }
                }
            }
        }
        // Remove user output data
        if let Some(index) = outputs.iter().position(|output| output.output_ptr() == data) {
            let mut removed_output = outputs.remove(index);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_output.frame_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_output.mode_listener()).link as *mut _ as _);
            // TODO Remove the rest of them
        }
    };
]);
<|endoftext|>


<commit_before>use parser::Identifier;
use operations::{Operation, Error};
use operations::item_type::{ItemType, FuncArgType};
use operations::scope::{ScopeStack, ScopeItem, TypeId};

pub fn define_u8(scope: &mut ScopeStack) -> TypeId {
    // Taking advantage of the scope system to simulate modules
    // This will be replaced with something better in:
    // https://github.com/brain-lang/brain/issues/37
    scope.push_scope();

    let unit_type = scope.primitives().unit();

    let u8_type = scope.declare_type(
        Identifier::from("u8"),
        ItemType::Primitive(1)
    );
    scope.register_primitive("u8", u8_type);

    scope.declare_builtin_function(
        // Special method for converting from literal
        // This name is such that it could never be called directly
        // from the language itself
        Identifier::from("std::convert::From<{unsigned integer}>"),
        ItemType::Function {
            // This takes a single literal of the type specific within
            // the curly braces {} in the name
            args: vec![FuncArgType::Array {item: u8_type, size: None}],
            // Return type signifies which type we are declaring supports integer literals
            return_type: u8_type,
        },
        move |scope, args, target| {
            let value = args[0].numeric_literal_value();

            // 8 is the size of this numeric type in bytes
            // We use >= here because 0 is reserved for zero so we
            // have (2^size - 1) numbers available
            if value >= (1 << 8) {
                Err(Error::OverflowingLiteral {
                    typ: scope.get_type(u8_type).clone()
                })
            }
            else {
                Ok(vec![
                    Operation::Increment {
                        target: target.position(),
                        amount: value as usize,
                    }
                ])
            }
        }
    );

    scope.declare_builtin_function(
        // Special method for displaying this primitive (used from print/println)
        // This name is such that it could never be called directly
        // from the language itself
        Identifier::from("std::fmt::Display::print"),
        ItemType::Function {
            args: vec![FuncArgType::Arg(u8_type)],
            return_type: unit_type,
        },
        move |_scope, args, _target| {
            let mem = match args[0] {
                ScopeItem::TypedBlock {memory, ..} => memory,
                _ => unreachable!(),
            };

            Ok(vec![
                Operation::Write {
                    target: mem,
                }
            ])
        }
    );

    scope.declare_builtin_function(
        Identifier::from("increment"),
        ItemType::Function {
            args: vec![FuncArgType::Arg(u8_type)],
            return_type: unit_type,
        },
        move |_scope, args, _target| {
            let mem = match args[0] {
                ScopeItem::TypedBlock {memory, ..} => memory,
                _ => unreachable!(),
            };

            debug_assert!(mem.size() == 1);

            Ok(vec![
                Operation::Increment {
                    target: mem.position(),
                    amount: 1,
                }
            ])
        }
    );

    scope.declare_builtin_function(
        Identifier::from("decrement"),
        ItemType::Function {
            args: vec![FuncArgType::Arg(u8_type)],
            return_type: unit_type,
        },
        move |_scope, args, _target| {
            let mem = match args[0] {
                ScopeItem::TypedBlock {memory, ..} => memory,
                _ => unreachable!(),
            };

            debug_assert!(mem.size() == 1);

            Ok(vec![
                Operation::Decrement {
                    target: mem.position(),
                    amount: 1,
                }
            ])
        }
    );

    // Method on [u8; _]
    scope.declare_builtin_function(
        // Special method for displaying this primitive (used from print/println)
        // This name is such that it could never be called directly
        // from the language itself
        Identifier::from("std::fmt::Display::print"),
        ItemType::Function {
            args: vec![FuncArgType::Array {item: u8_type, size: None}],
            return_type: unit_type,
        },
        move |_scope, args, _target| {
            let mem = match args[0] {
                ScopeItem::Array {memory, ..} => memory,
                _ => unreachable!(),
            };

            Ok(vec![
                Operation::Write {
                    target: mem,
                }
            ])
        }
    );

    u8_type
}

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

    use operations::scope::{ScopeType};

    #[test]
    fn defines_primitive() {
        let mut scope = ScopeStack::new();
        define_u8(&mut scope);

        let u8_type_id = match **scope.lookup_type(&Identifier::from("u8")).first().unwrap() {
            ScopeType::Type(id) => id,
        };
        assert_eq!(scope.primitives().u8(), u8_type_id);
    }
}
<commit_msg>Fixed implementation of u8 print to get to the correct ascii code first (so numbers print as expected)<commit_after>use parser::Identifier;
use operations::{Operation, Error};
use operations::item_type::{ItemType, FuncArgType};
use operations::scope::{ScopeStack, ScopeItem, TypeId};

pub fn define_u8(scope: &mut ScopeStack) -> TypeId {
    // Taking advantage of the scope system to simulate modules
    // This will be replaced with something better in:
    // https://github.com/brain-lang/brain/issues/37
    scope.push_scope();

    let unit_type = scope.primitives().unit();

    let u8_type = scope.declare_type(
        Identifier::from("u8"),
        ItemType::Primitive(1)
    );
    scope.register_primitive("u8", u8_type);

    scope.declare_builtin_function(
        // Special method for converting from literal
        // This name is such that it could never be called directly
        // from the language itself
        Identifier::from("std::convert::From<{unsigned integer}>"),
        ItemType::Function {
            // This takes a single literal of the type specific within
            // the curly braces {} in the name
            args: vec![FuncArgType::Array {item: u8_type, size: None}],
            // Return type signifies which type we are declaring supports integer literals
            return_type: u8_type,
        },
        move |scope, args, target| {
            let value = args[0].numeric_literal_value();

            // 8 is the size of this numeric type in bytes
            // We use >= here because 0 is reserved for zero so we
            // have (2^size - 1) numbers available
            if value >= (1 << 8) {
                Err(Error::OverflowingLiteral {
                    typ: scope.get_type(u8_type).clone()
                })
            }
            else {
                Ok(vec![
                    Operation::Increment {
                        target: target.position(),
                        amount: value as usize,
                    }
                ])
            }
        }
    );

    scope.declare_builtin_function(
        // Special method for displaying this primitive (used from print/println)
        // This name is such that it could never be called directly
        // from the language itself
        Identifier::from("std::fmt::Display::print"),
        ItemType::Function {
            args: vec![FuncArgType::Arg(u8_type)],
            return_type: unit_type,
        },
        move |_, args, _| {
            let mem = match args[0] {
                ScopeItem::TypedBlock {memory, ..} => memory,
                _ => unreachable!(),
            };

            Ok(vec![
                // Need to display numbers as numbers by first incrementing them to the proper
                // ascii code and then decrementing them again
                Operation::Increment {
                    target: mem.position(),
                    amount: b'0',
                },
                Operation::Write {
                    target: mem,
                },
                // Need to make sure we reverse the operation after or else there will be
                // unintended consequences
                Operation::Decrement {
                    target: mem.position(),
                    amount: b'0',
                },
            ])
        }
    );

    scope.declare_builtin_function(
        Identifier::from("increment"),
        ItemType::Function {
            args: vec![FuncArgType::Arg(u8_type)],
            return_type: unit_type,
        },
        move |_scope, args, _target| {
            let mem = match args[0] {
                ScopeItem::TypedBlock {memory, ..} => memory,
                _ => unreachable!(),
            };

            debug_assert!(mem.size() == 1);

            Ok(vec![
                Operation::Increment {
                    target: mem.position(),
                    amount: 1,
                }
            ])
        }
    );

    scope.declare_builtin_function(
        Identifier::from("decrement"),
        ItemType::Function {
            args: vec![FuncArgType::Arg(u8_type)],
            return_type: unit_type,
        },
        move |_scope, args, _target| {
            let mem = match args[0] {
                ScopeItem::TypedBlock {memory, ..} => memory,
                _ => unreachable!(),
            };

            debug_assert!(mem.size() == 1);

            Ok(vec![
                Operation::Decrement {
                    target: mem.position(),
                    amount: 1,
                }
            ])
        }
    );

    // Method on [u8; _]
    scope.declare_builtin_function(
        // Special method for displaying this primitive (used from print/println)
        // This name is such that it could never be called directly
        // from the language itself
        Identifier::from("std::fmt::Display::print"),
        ItemType::Function {
            args: vec![FuncArgType::Array {item: u8_type, size: None}],
            return_type: unit_type,
        },
        move |_scope, args, _target| {
            let mem = match args[0] {
                ScopeItem::Array {memory, ..} => memory,
                _ => unreachable!(),
            };

            Ok(vec![
                Operation::Write {
                    target: mem,
                }
            ])
        }
    );

    u8_type
}

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

    use operations::scope::{ScopeType};

    #[test]
    fn defines_primitive() {
        let mut scope = ScopeStack::new();
        define_u8(&mut scope);

        let u8_type_id = match **scope.lookup_type(&Identifier::from("u8")).first().unwrap() {
            ScopeType::Type(id) => id,
        };
        assert_eq!(scope.primitives().u8(), u8_type_id);
    }
}
<|endoftext|>


<commit_before>use decoders::basics::*;

pub mod huffman;
mod decompressors;
use decoders::ljpeg::huffman::*;
use decoders::ljpeg::decompressors::*;

enum Marker {
  Stuff        = 0x00,
  SOF3         = 0xc3, // lossless
  DHT          = 0xc4, // huffman tables
  SOI          = 0xd8, // start of image
  EOI          = 0xd9, // end of image
  SOS          = 0xda, // start of scan
  DQT          = 0xdb, // quantization tables
  Fill         = 0xff,
}

fn m(marker: Marker) -> u8 {
  marker as u8
}

#[derive(Debug, Copy, Clone)]
struct JpegComponentInfo {
  // These values are fixed over the whole image, read from the SOF marker.
  id: usize,    // identifier for this component (0..255)
  index: usize, // its index in SOF or cPtr->compInfo[]

  // Huffman table selector (0..3). The value may vary between scans.
  // It is read from the SOS marker.
  dc_tbl_num: usize,
  super_h: usize, // Horizontal Supersampling
  super_v: usize, // Vertical Supersampling
}

#[derive(Debug, Clone)]
struct SOFInfo {
  width: usize,
  height: usize,
  cps: usize,
  precision: usize,
  components: Vec<JpegComponentInfo>,
}

impl SOFInfo {
  fn empty() -> SOFInfo {
    SOFInfo {
      width: 0,
      height: 0,
      cps: 0,
      precision: 0,
      components: Vec::new(),
    }
  }

  fn parse_sof(&mut self, input: &mut ByteStream) -> Result<(), String> {
    let header_length = input.get_u16() as usize;
    self.precision = input.get_u8() as usize;
    self.height = input.get_u16() as usize;
    self.width = input.get_u16() as usize;
    self.cps = input.get_u8() as usize;

    if self.precision > 16 {
      return Err("ljpeg: More than 16 bits per channel is not supported.".to_string())
    }
    if self.cps > 4 || self.cps < 1 {
      return Err("ljpeg: Only from 1 to 4 components are supported.".to_string())
    }
    if header_length != 8 + self.cps*3 {
      return Err("ljpeg: Header size mismatch.".to_string())
    }

    for i in 0..self.cps {
      let id = input.get_u8() as usize;
      let subs = input.get_u8() as usize;
      if input.get_u8() != 0 {
        return Err("ljpeg: Quantized components not supported.".to_string())
      }
      self.components.push(JpegComponentInfo {
        id: id,
        index: i,
        dc_tbl_num: 0,
        super_h: subs & 0xf,
        super_v: subs >> 4,
      });
    }
    Ok(())
  }

  fn parse_sos(&mut self, input: &mut ByteStream) -> Result<(usize, usize), String> {
    if self.width == 0 {
      return Err("ljpeg: Trying to parse SOS before SOF".to_string())
    }
    input.get_u16(); //skip header length
    let soscps = input.get_u8() as usize;
    if self.cps != soscps {
      return Err("ljpeg: component number mismatch in SOS".to_string())
    }
    for _ in 0..self.cps {
      let cs = input.get_u8() as usize;
      let component = match self.components.iter_mut().find(|&&mut c| c.id == cs) {
        Some(val) => val,
        None => return Err("ljpeg: invalid component selector".to_string())
      };
      let td = (input.get_u8() as usize) >> 4;
      if td > 3 {
        return Err("ljpeg: Invalid Huffman table selection".to_string())
      }
      component.dc_tbl_num = td;
    }
    let pred = input.get_u8() as usize;
    input.get_u8();                           // Se + Ah Not used in LJPEG
    let pt = (input.get_u8() as usize) & 0xf; // Point Transform
    Ok((pred, pt))
  }
}

#[derive(Debug)]
pub struct LjpegDecompressor<'a> {
  buffer: &'a [u8],
  sof: SOFInfo,
  predictor: usize,
  point_transform: usize,
  dhts: Vec<HuffTable>,
}

impl<'a> LjpegDecompressor<'a> {
  pub fn new(src: &'a [u8], use_bigtable: bool) -> Result<LjpegDecompressor, String> {
    let mut input = ByteStream::new(src, BIG_ENDIAN);
    if try!(LjpegDecompressor::get_next_marker(&mut input, false)) != m(Marker::SOI) {
      return Err("ljpeg: Image did not start with SOI. Probably not LJPEG".to_string())
    }

    let mut sof = SOFInfo::empty();
    let mut dht_init = [false;4];
    let mut dht_bits = [[0 as u32;17];4];
    let mut dht_huffval = [[0 as u32;256];4];
    let pred;
    let pt;
    loop {
      let marker = try!(LjpegDecompressor::get_next_marker(&mut input, true));
      if marker == m(Marker::SOF3) {
        // Start of the frame, giving us the basic info
        try!(sof.parse_sof(&mut input));
        if sof.precision > 16 || sof.precision < 12 {
          return Err(format!("ljpeg: sof.precision {}", sof.precision).to_string())
        }
      } else if marker == m(Marker::DHT) {
        // Huffman table settings
        try!(LjpegDecompressor::parse_dht(&mut input, &mut dht_init, &mut dht_bits, &mut dht_huffval));
      } else if marker == m(Marker::SOS) {
        // Start of the actual stream, we can decode after this
        let (a, b) = try!(sof.parse_sos(&mut input));
        pred = a; pt = b;
        break;
      } else if marker == m(Marker::EOI) {
        // Should never be reached as we stop at SOS
        return Err("ljpeg: reached EOI before SOS".to_string())
      } else if marker == m(Marker::DQT) {
        return Err("ljpeg: not a valid raw file, found DQT".to_string())
      }
    }

    let mut dhts = Vec::new();
    for i in 0..4 {
      dhts.push(if dht_init[i] {
        try!(HuffTable::new(dht_bits[i], dht_huffval[i], sof.precision, use_bigtable))
      } else {
        HuffTable::empty(0)
      });
    }

    let offset = input.get_pos();
    Ok(LjpegDecompressor {
      buffer: &src[offset..],
      sof: sof,
      predictor: pred,
      point_transform: pt,
      dhts: dhts,
    })
  }

  fn get_next_marker(input: &mut ByteStream, allowskip:bool) -> Result<u8,String> {
    if !allowskip {
      if input.get_u8() != 0xff {
        return Err("ljpeg: (noskip) expected marker not found".to_string())
      }
      let mark = input.get_u8();
      if mark == m(Marker::Stuff) || mark == m(Marker::Fill) {
        return Err("ljpeg: (noskip) expected marker but found stuff or fill".to_string())
      }
      return Ok(mark)
    }
    try!(input.skip_to_marker());

    Ok(input.get_u8())
  }

  fn parse_dht(input: &mut ByteStream, init: &mut [bool;4], bits: &mut [[u32;17];4], huffval: &mut [[u32;256];4]) -> Result<(), String> {
    let mut length = (input.get_u16() as usize) - 2;

    while length > 0 {
      let b = input.get_u8() as usize;
      let tc = b >> 4;
      let th = b & 0xf;

      if tc != 0 {
        return Err("ljpeg: unsuported table class in DHT".to_string())
      }
      if th > 3 {
        return Err(format!("ljpeg: unsuported table id {}", th).to_string())
      }

      let mut acc: usize = 0;
      for i in 0..16 {
        bits[th][i+1] = input.get_u8() as u32;
        acc += bits[th][i+1] as usize;
      }
      bits[th][0] = 0;

      if acc > 256 {
        return Err("ljpeg: invalid DHT table".to_string())
      }

      if length < 1+16+acc {
        return Err("ljpeg: invalid DHT table length".to_string())
      }

      for i in 0..acc {
        huffval[th][i] = input.get_u8() as u32;
      }

      init[th] = true;
      length -= 1 + 16 + acc;
    }

    Ok(())
  }

  pub fn decode(&self, out: &mut [u16], x: usize, stripwidth: usize, width: usize, height: usize) -> Result<(),String> {
    if self.sof.components[0].super_h == 2 && self.sof.components[0].super_v == 2 {
      return decode_ljpeg_420(self, out, width, height)
    } else if self.sof.components[0].super_h == 2 && self.sof.components[0].super_v == 1 {
      return Err("YUV422 not supported yet".to_string())
    }

    match self.predictor {
      1 => {
        match self.sof.cps {
          2 => decode_ljpeg_2components(self, out, x, stripwidth, width, height),
          4 => decode_ljpeg_4components(self, out, width, height),
          c => return Err(format!("ljpeg: {} component files not supported", c).to_string()),
        }
      },
      8 => decode_hasselblad(self, out, width),
      p => return Err(format!("ljpeg: predictor {} not supported", p).to_string()),
    }
  }

  pub fn width(&self) -> usize { self.sof.width * self.sof.cps }
  pub fn height(&self) -> usize { self.sof.height }
  pub fn super_v(&self) -> usize { self.sof.components[0].super_v }
  pub fn super_h(&self) -> usize { self.sof.components[0].super_h }
}
<commit_msg>ljpeg: swap super_h/super_v the correct way<commit_after>use decoders::basics::*;

pub mod huffman;
mod decompressors;
use decoders::ljpeg::huffman::*;
use decoders::ljpeg::decompressors::*;

enum Marker {
  Stuff        = 0x00,
  SOF3         = 0xc3, // lossless
  DHT          = 0xc4, // huffman tables
  SOI          = 0xd8, // start of image
  EOI          = 0xd9, // end of image
  SOS          = 0xda, // start of scan
  DQT          = 0xdb, // quantization tables
  Fill         = 0xff,
}

fn m(marker: Marker) -> u8 {
  marker as u8
}

#[derive(Debug, Copy, Clone)]
struct JpegComponentInfo {
  // These values are fixed over the whole image, read from the SOF marker.
  id: usize,    // identifier for this component (0..255)
  index: usize, // its index in SOF or cPtr->compInfo[]

  // Huffman table selector (0..3). The value may vary between scans.
  // It is read from the SOS marker.
  dc_tbl_num: usize,
  super_h: usize, // Horizontal Supersampling
  super_v: usize, // Vertical Supersampling
}

#[derive(Debug, Clone)]
struct SOFInfo {
  width: usize,
  height: usize,
  cps: usize,
  precision: usize,
  components: Vec<JpegComponentInfo>,
}

impl SOFInfo {
  fn empty() -> SOFInfo {
    SOFInfo {
      width: 0,
      height: 0,
      cps: 0,
      precision: 0,
      components: Vec::new(),
    }
  }

  fn parse_sof(&mut self, input: &mut ByteStream) -> Result<(), String> {
    let header_length = input.get_u16() as usize;
    self.precision = input.get_u8() as usize;
    self.height = input.get_u16() as usize;
    self.width = input.get_u16() as usize;
    self.cps = input.get_u8() as usize;

    if self.precision > 16 {
      return Err("ljpeg: More than 16 bits per channel is not supported.".to_string())
    }
    if self.cps > 4 || self.cps < 1 {
      return Err("ljpeg: Only from 1 to 4 components are supported.".to_string())
    }
    if header_length != 8 + self.cps*3 {
      return Err("ljpeg: Header size mismatch.".to_string())
    }

    for i in 0..self.cps {
      let id = input.get_u8() as usize;
      let subs = input.get_u8() as usize;
      if input.get_u8() != 0 {
        return Err("ljpeg: Quantized components not supported.".to_string())
      }
      self.components.push(JpegComponentInfo {
        id: id,
        index: i,
        dc_tbl_num: 0,
        super_v: subs & 0xf,
        super_h: subs >> 4,
      });
    }
    Ok(())
  }

  fn parse_sos(&mut self, input: &mut ByteStream) -> Result<(usize, usize), String> {
    if self.width == 0 {
      return Err("ljpeg: Trying to parse SOS before SOF".to_string())
    }
    input.get_u16(); //skip header length
    let soscps = input.get_u8() as usize;
    if self.cps != soscps {
      return Err("ljpeg: component number mismatch in SOS".to_string())
    }
    for _ in 0..self.cps {
      let cs = input.get_u8() as usize;
      let component = match self.components.iter_mut().find(|&&mut c| c.id == cs) {
        Some(val) => val,
        None => return Err("ljpeg: invalid component selector".to_string())
      };
      let td = (input.get_u8() as usize) >> 4;
      if td > 3 {
        return Err("ljpeg: Invalid Huffman table selection".to_string())
      }
      component.dc_tbl_num = td;
    }
    let pred = input.get_u8() as usize;
    input.get_u8();                           // Se + Ah Not used in LJPEG
    let pt = (input.get_u8() as usize) & 0xf; // Point Transform
    Ok((pred, pt))
  }
}

#[derive(Debug)]
pub struct LjpegDecompressor<'a> {
  buffer: &'a [u8],
  sof: SOFInfo,
  predictor: usize,
  point_transform: usize,
  dhts: Vec<HuffTable>,
}

impl<'a> LjpegDecompressor<'a> {
  pub fn new(src: &'a [u8], use_bigtable: bool) -> Result<LjpegDecompressor, String> {
    let mut input = ByteStream::new(src, BIG_ENDIAN);
    if try!(LjpegDecompressor::get_next_marker(&mut input, false)) != m(Marker::SOI) {
      return Err("ljpeg: Image did not start with SOI. Probably not LJPEG".to_string())
    }

    let mut sof = SOFInfo::empty();
    let mut dht_init = [false;4];
    let mut dht_bits = [[0 as u32;17];4];
    let mut dht_huffval = [[0 as u32;256];4];
    let pred;
    let pt;
    loop {
      let marker = try!(LjpegDecompressor::get_next_marker(&mut input, true));
      if marker == m(Marker::SOF3) {
        // Start of the frame, giving us the basic info
        try!(sof.parse_sof(&mut input));
        if sof.precision > 16 || sof.precision < 12 {
          return Err(format!("ljpeg: sof.precision {}", sof.precision).to_string())
        }
      } else if marker == m(Marker::DHT) {
        // Huffman table settings
        try!(LjpegDecompressor::parse_dht(&mut input, &mut dht_init, &mut dht_bits, &mut dht_huffval));
      } else if marker == m(Marker::SOS) {
        // Start of the actual stream, we can decode after this
        let (a, b) = try!(sof.parse_sos(&mut input));
        pred = a; pt = b;
        break;
      } else if marker == m(Marker::EOI) {
        // Should never be reached as we stop at SOS
        return Err("ljpeg: reached EOI before SOS".to_string())
      } else if marker == m(Marker::DQT) {
        return Err("ljpeg: not a valid raw file, found DQT".to_string())
      }
    }

    let mut dhts = Vec::new();
    for i in 0..4 {
      dhts.push(if dht_init[i] {
        try!(HuffTable::new(dht_bits[i], dht_huffval[i], sof.precision, use_bigtable))
      } else {
        HuffTable::empty(0)
      });
    }

    let offset = input.get_pos();
    Ok(LjpegDecompressor {
      buffer: &src[offset..],
      sof: sof,
      predictor: pred,
      point_transform: pt,
      dhts: dhts,
    })
  }

  fn get_next_marker(input: &mut ByteStream, allowskip:bool) -> Result<u8,String> {
    if !allowskip {
      if input.get_u8() != 0xff {
        return Err("ljpeg: (noskip) expected marker not found".to_string())
      }
      let mark = input.get_u8();
      if mark == m(Marker::Stuff) || mark == m(Marker::Fill) {
        return Err("ljpeg: (noskip) expected marker but found stuff or fill".to_string())
      }
      return Ok(mark)
    }
    try!(input.skip_to_marker());

    Ok(input.get_u8())
  }

  fn parse_dht(input: &mut ByteStream, init: &mut [bool;4], bits: &mut [[u32;17];4], huffval: &mut [[u32;256];4]) -> Result<(), String> {
    let mut length = (input.get_u16() as usize) - 2;

    while length > 0 {
      let b = input.get_u8() as usize;
      let tc = b >> 4;
      let th = b & 0xf;

      if tc != 0 {
        return Err("ljpeg: unsuported table class in DHT".to_string())
      }
      if th > 3 {
        return Err(format!("ljpeg: unsuported table id {}", th).to_string())
      }

      let mut acc: usize = 0;
      for i in 0..16 {
        bits[th][i+1] = input.get_u8() as u32;
        acc += bits[th][i+1] as usize;
      }
      bits[th][0] = 0;

      if acc > 256 {
        return Err("ljpeg: invalid DHT table".to_string())
      }

      if length < 1+16+acc {
        return Err("ljpeg: invalid DHT table length".to_string())
      }

      for i in 0..acc {
        huffval[th][i] = input.get_u8() as u32;
      }

      init[th] = true;
      length -= 1 + 16 + acc;
    }

    Ok(())
  }

  pub fn decode(&self, out: &mut [u16], x: usize, stripwidth: usize, width: usize, height: usize) -> Result<(),String> {
    if self.sof.components[0].super_h == 2 && self.sof.components[0].super_v == 2 {
      return decode_ljpeg_420(self, out, width, height)
    } else if self.sof.components[0].super_h == 2 && self.sof.components[0].super_v == 1 {
      return Err("YUV422 not supported yet".to_string())
    }

    match self.predictor {
      1 => {
        match self.sof.cps {
          2 => decode_ljpeg_2components(self, out, x, stripwidth, width, height),
          4 => decode_ljpeg_4components(self, out, width, height),
          c => return Err(format!("ljpeg: {} component files not supported", c).to_string()),
        }
      },
      8 => decode_hasselblad(self, out, width),
      p => return Err(format!("ljpeg: predictor {} not supported", p).to_string()),
    }
  }

  pub fn width(&self) -> usize { self.sof.width * self.sof.cps }
  pub fn height(&self) -> usize { self.sof.height }
  pub fn super_v(&self) -> usize { self.sof.components[0].super_v }
  pub fn super_h(&self) -> usize { self.sof.components[0].super_h }
}
<|endoftext|>


<commit_before>//! Defines the render target for tray, where our image will be written too
//! during rendering
//! TODO: Reconstruction filters

use std::vec::Vec;
use std::{iter, cmp, f32};
use std::sync::Mutex;

use film::Colorf;
use film::filter::Filter;
use sampler::Region;

const FILTER_TABLE_SIZE: usize = 16;

/// A struct containing results of an image sample where a ray was fired through
/// continuous pixel coordinates [x, y] and color `color` was computed
pub struct ImageSample {
    pub x: f32,
    pub y: f32,
    pub color: Colorf,
}

impl ImageSample {
    pub fn new(x: f32, y: f32, color: Colorf) -> ImageSample {
        ImageSample { x: x, y: y, color: color }
    }
}

/// RenderTarget is a RGBF render target to write our image too while rendering
pub struct RenderTarget {
    width: usize,
    height: usize,
    pixels: Vec<Colorf>,
    pixels_locked: Vec<Mutex<Vec<Colorf>>>,
    lock_size: (i32, i32),
    filter: Box<Filter + Send + Sync>,
    filter_table: Vec<f32>,
}

impl RenderTarget {
    /// Create a render target with `width * height` pixels
    pub fn new(image_dim: (usize, usize), lock_size: (usize, usize), filter: Box<Filter + Send + Sync>) -> RenderTarget {
        if image_dim.0 % lock_size.0 != 0 || image_dim.1 % lock_size.1 != 0 {
            panic!("Image with dimension {:?} not evenly divided by blocks of {:?}", image_dim, lock_size);
        }
        let width = image_dim.0;
        let height = image_dim.1;
        let mut filter_table: Vec<f32> = iter::repeat(0.0).take(FILTER_TABLE_SIZE * FILTER_TABLE_SIZE)
            .collect();
        for y in 0..FILTER_TABLE_SIZE {
            let fy = (y as f32 + 0.5) * filter.height() / FILTER_TABLE_SIZE as f32;
            for x in 0..FILTER_TABLE_SIZE {
                let fx = (x as f32 + 0.5) * filter.width() / FILTER_TABLE_SIZE as f32;
                filter_table[y * FILTER_TABLE_SIZE + x] = filter.weight(fx, fy);
            }
        }
        let x_blocks = width / lock_size.0;
        let y_blocks = height / lock_size.1;
        println!("x_blocks = {}, y_blocks = {}", x_blocks, y_blocks);
        println!("width / 0.5 = {}, height / 0.5 = {}", f32::floor(filter.width() / 0.5),
            f32::floor(filter.height() / 0.5));
        let mut pixels_locked = Vec::with_capacity(x_blocks * y_blocks);
        for _ in 0..x_blocks * y_blocks {
            pixels_locked.push(Mutex::new(iter::repeat(Colorf::broadcast(0.0)).take(lock_size.0 * lock_size.1).collect()));
        }
        RenderTarget { width: width, height: height,
            pixels: iter::repeat(Colorf::broadcast(0.0)).take(width * height).collect(),
            pixels_locked: pixels_locked,
            lock_size: (lock_size.0 as i32, lock_size.1 as i32),
            filter: filter,
            filter_table: filter_table,
        }
    }
    /// Write a color value to the image at `(x, y)`
    pub fn write(&mut self, x: f32, y: f32, c: &Colorf) {
        // Compute the discrete pixel coordinates which the sample hits
        let img_x = x - 0.5;
        let img_y = y - 0.5;
        let x_range = (f32::max(f32::ceil(img_x - self.filter.width()), 0.0) as usize,
                       f32::min(f32::floor(img_x + self.filter.width()),
                           self.width as f32 - 1.0) as usize);
        let y_range = (f32::max(f32::ceil(img_y - self.filter.height()), 0.0) as usize,
                       f32::min(f32::floor(img_y + self.filter.height()),
                           self.height as f32 - 1.0) as usize);
        if (x_range.1 as isize) - (x_range.0 as isize) < 0
            || (y_range.1 as isize) - (y_range.0 as isize) < 0 {
                return;
        }
        for iy in y_range.0..(y_range.1 + 1) {
            let fy = f32::abs(iy as f32 - img_y) * self.filter.inv_height() * FILTER_TABLE_SIZE as f32;
            let fy_idx = cmp::min(fy as usize, FILTER_TABLE_SIZE - 1);
            for ix in x_range.0..(x_range.1 + 1) {
                let fx = f32::abs(ix as f32 - img_x) * self.filter.inv_width() * FILTER_TABLE_SIZE as f32;
                let fx_idx = cmp::min(fx as usize, FILTER_TABLE_SIZE - 1);
                let weight = self.filter_table[fy_idx * FILTER_TABLE_SIZE + fx_idx];
                // TODO: Can't currently overload the += operator
                // Coming soon though, see RFC #953 https://github.com/rust-lang/rfcs/pull/953
                self.pixels[iy * self.width + ix].r += weight * c.r;
                self.pixels[iy * self.width + ix].g += weight * c.g;
                self.pixels[iy * self.width + ix].b += weight * c.b;
                self.pixels[iy * self.width + ix].a += weight;
            }
        }
    }
    /// Write all the color values to the image
    /// TODO: This code can definitely be optimized and cleaned up
    pub fn write_block(&self, samples: &Vec<ImageSample>, region: &Region) {
        // Determine which blocks we touch with our set of samples
        let filter_pixels = (f32::floor(self.filter.width() / 0.5) as i32,
                             f32::floor(self.filter.height() / 0.5) as i32);
        let x_range = (cmp::max(region.start.0 as i32 - filter_pixels.0, 0),
                       cmp::min(region.end.0 as i32 + filter_pixels.0, self.width as i32 - 1));
        let y_range = (cmp::max(region.start.1 as i32 - filter_pixels.1, 0),
                       cmp::min(region.end.1 as i32 + filter_pixels.1, self.height as i32 - 1));
        /*
        println!("Writing starting at {:?} with filter pixels = {:?}\n\tx_range = {:?}, y_range = {:?}",
                 region.start, filter_pixels, x_range, y_range);
         */
        let block_x_range = (x_range.0 / self.lock_size.0, x_range.1 / self.lock_size.0);
        let block_y_range = (y_range.0 / self.lock_size.1, y_range.1 / self.lock_size.1);
        //println!("\tBlock x range {:?}, y range {:?}", block_x_range, block_y_range);
        if x_range.1 - x_range.0 < 0 || y_range.1 - y_range.0 < 0 {
                return;
        }
        let blocks_per_row = self.width as i32 / self.lock_size.0;
        for y in block_y_range.0..block_y_range.1 + 1 {
            for x in block_x_range.0..block_x_range.1 + 1 {
                //println!("\tBlock [{}, {}] is index {}", x, y, y * blocks_per_row + x);
                let x_write_range = (cmp::max(x_range.0, x * self.lock_size.0),
                                     cmp::min(x_range.1 + 1, x * self.lock_size.0 + self.lock_size.0));
                let y_write_range = (cmp::max(y_range.0, y * self.lock_size.1),
                                     cmp::min(y_range.1 + 1, y * self.lock_size.1 + self.lock_size.1));
                //println!("\tWriting to pixels x range: {:?}, y range {:?}", x_write_range, y_write_range);
                let block_samples = samples.iter().filter(|s| {
                    s.x >= (x_write_range.0 - filter_pixels.0) as f32
                        && s.x < (x_write_range.1 + filter_pixels.0) as f32
                        && s.y >= (y_write_range.0 - filter_pixels.1) as f32
                        && s.y < (y_write_range.1 + filter_pixels.1) as f32
                });
                // Acquire lock for the block and write the samples
                // TODO: Move more work out of critical section. We only need to store the actual
                // final filtered pixel values for the region, not weights + filtered vals for each
                // sample
                let block_idx = (y * blocks_per_row + x) as usize;
                let mut pixels = self.pixels_locked[block_idx].lock().unwrap();
                for c in block_samples {
                    let img_x = c.x - 0.5;
                    let img_y = c.y - 0.5;
                    for iy in y_write_range.0..y_write_range.1 {
                        let fy = f32::abs(iy as f32 - img_y) * self.filter.inv_height()
                            * FILTER_TABLE_SIZE as f32;
                        let fy_idx = cmp::min(fy as usize, FILTER_TABLE_SIZE - 1);
                        for ix in x_write_range.0..x_write_range.1 {
                            let fx = f32::abs(ix as f32 - img_x) * self.filter.inv_width()
                                * FILTER_TABLE_SIZE as f32;
                            let fx_idx = cmp::min(fx as usize, FILTER_TABLE_SIZE - 1);
                            let weight = self.filter_table[fy_idx * FILTER_TABLE_SIZE + fx_idx];
                            let px = ((iy - y * self.lock_size.0) * self.lock_size.0 + ix - x * self.lock_size.0) as usize;
                            // TODO: Can't currently overload the += operator
                            // Coming soon though, see RFC #953 https://github.com/rust-lang/rfcs/pull/953
                            //println!("\tWriting pixel [{}, {}], block pix index = {}", ix, iy, px);
                            pixels[px].r += weight * c.color.r;
                            pixels[px].g += weight * c.color.g;
                            pixels[px].b += weight * c.color.b;
                            pixels[px].a += weight;
                        }
                    }
                }
            }
        }
    }
    /// Clear the render target to black
    pub fn clear(&mut self) {
        for p in self.pixels.iter_mut() {
            *p = Colorf::broadcast(0.0);
        }
    }
    /// Get the dimensions of the render target
    pub fn dimensions(&self) -> (usize, usize) {
        (self.width, self.height)
    }
    /// Convert the floating point color buffer to 24bpp sRGB for output to an image
    pub fn get_render(&self) -> Vec<u8> {
        let mut render: Vec<u8> = iter::repeat(0u8).take(self.width * self.height * 3).collect();
        let x_blocks = self.width / self.lock_size.0 as usize;
        let y_blocks = self.height / self.lock_size.1 as usize;
        for by in 0..y_blocks {
            for bx in 0..x_blocks {
                let block_idx = (by * x_blocks + bx) as usize;
                let pixels = self.pixels_locked[block_idx].lock().unwrap();
                for y in 0..self.lock_size.1 as usize {
                    for x in 0..self.lock_size.0 as usize {
                        let c = &pixels[y * self.lock_size.0 as usize+ x];
                        if c.a > 0.0 {
                            let cn = (*c / c.a).clamp().to_srgb();
                            let px = (y + by * self.lock_size.0 as usize) * self.width * 3
                                    + (x + bx * self.lock_size.0 as usize) * 3;
                            for i in 0..3 {
                                render[px + i] = (cn[i] * 255.0) as u8;
                            }
                        }
                    }
                }
            }
        }
        render
    }
}

<commit_msg>Compute filtered pixel values before acquiring the lock<commit_after>//! Defines the render target for tray, where our image will be written too
//! during rendering
//! TODO: Reconstruction filters

use std::vec::Vec;
use std::{iter, cmp, f32};
use std::sync::Mutex;

use film::Colorf;
use film::filter::Filter;
use sampler::Region;

const FILTER_TABLE_SIZE: usize = 16;

/// A struct containing results of an image sample where a ray was fired through
/// continuous pixel coordinates [x, y] and color `color` was computed
pub struct ImageSample {
    pub x: f32,
    pub y: f32,
    pub color: Colorf,
}

impl ImageSample {
    pub fn new(x: f32, y: f32, color: Colorf) -> ImageSample {
        ImageSample { x: x, y: y, color: color }
    }
}

/// RenderTarget is a RGBF render target to write our image too while rendering
pub struct RenderTarget {
    width: usize,
    height: usize,
    pixels: Vec<Colorf>,
    pixels_locked: Vec<Mutex<Vec<Colorf>>>,
    lock_size: (i32, i32),
    filter: Box<Filter + Send + Sync>,
    filter_table: Vec<f32>,
}

impl RenderTarget {
    /// Create a render target with `width * height` pixels
    pub fn new(image_dim: (usize, usize), lock_size: (usize, usize), filter: Box<Filter + Send + Sync>) -> RenderTarget {
        if image_dim.0 % lock_size.0 != 0 || image_dim.1 % lock_size.1 != 0 {
            panic!("Image with dimension {:?} not evenly divided by blocks of {:?}", image_dim, lock_size);
        }
        let width = image_dim.0;
        let height = image_dim.1;
        let mut filter_table: Vec<f32> = iter::repeat(0.0).take(FILTER_TABLE_SIZE * FILTER_TABLE_SIZE)
            .collect();
        for y in 0..FILTER_TABLE_SIZE {
            let fy = (y as f32 + 0.5) * filter.height() / FILTER_TABLE_SIZE as f32;
            for x in 0..FILTER_TABLE_SIZE {
                let fx = (x as f32 + 0.5) * filter.width() / FILTER_TABLE_SIZE as f32;
                filter_table[y * FILTER_TABLE_SIZE + x] = filter.weight(fx, fy);
            }
        }
        let x_blocks = width / lock_size.0;
        let y_blocks = height / lock_size.1;
        println!("x_blocks = {}, y_blocks = {}", x_blocks, y_blocks);
        println!("width / 0.5 = {}, height / 0.5 = {}", f32::floor(filter.width() / 0.5),
            f32::floor(filter.height() / 0.5));
        let mut pixels_locked = Vec::with_capacity(x_blocks * y_blocks);
        for _ in 0..x_blocks * y_blocks {
            pixels_locked.push(Mutex::new(iter::repeat(Colorf::broadcast(0.0)).take(lock_size.0 * lock_size.1).collect()));
        }
        RenderTarget { width: width, height: height,
            pixels: iter::repeat(Colorf::broadcast(0.0)).take(width * height).collect(),
            pixels_locked: pixels_locked,
            lock_size: (lock_size.0 as i32, lock_size.1 as i32),
            filter: filter,
            filter_table: filter_table,
        }
    }
    /// Write a color value to the image at `(x, y)`
    pub fn write(&mut self, x: f32, y: f32, c: &Colorf) {
        // Compute the discrete pixel coordinates which the sample hits
        let img_x = x - 0.5;
        let img_y = y - 0.5;
        let x_range = (f32::max(f32::ceil(img_x - self.filter.width()), 0.0) as usize,
                       f32::min(f32::floor(img_x + self.filter.width()),
                           self.width as f32 - 1.0) as usize);
        let y_range = (f32::max(f32::ceil(img_y - self.filter.height()), 0.0) as usize,
                       f32::min(f32::floor(img_y + self.filter.height()),
                           self.height as f32 - 1.0) as usize);
        if (x_range.1 as isize) - (x_range.0 as isize) < 0
            || (y_range.1 as isize) - (y_range.0 as isize) < 0 {
                return;
        }
        for iy in y_range.0..(y_range.1 + 1) {
            let fy = f32::abs(iy as f32 - img_y) * self.filter.inv_height() * FILTER_TABLE_SIZE as f32;
            let fy_idx = cmp::min(fy as usize, FILTER_TABLE_SIZE - 1);
            for ix in x_range.0..(x_range.1 + 1) {
                let fx = f32::abs(ix as f32 - img_x) * self.filter.inv_width() * FILTER_TABLE_SIZE as f32;
                let fx_idx = cmp::min(fx as usize, FILTER_TABLE_SIZE - 1);
                let weight = self.filter_table[fy_idx * FILTER_TABLE_SIZE + fx_idx];
                // TODO: Can't currently overload the += operator
                // Coming soon though, see RFC #953 https://github.com/rust-lang/rfcs/pull/953
                self.pixels[iy * self.width + ix].r += weight * c.r;
                self.pixels[iy * self.width + ix].g += weight * c.g;
                self.pixels[iy * self.width + ix].b += weight * c.b;
                self.pixels[iy * self.width + ix].a += weight;
            }
        }
    }
    /// Write all the color values to the image
    /// TODO: This code can definitely be optimized and cleaned up
    pub fn write_block(&self, samples: &Vec<ImageSample>, region: &Region) {
        // Determine which blocks we touch with our set of samples
        let filter_pixels = (f32::floor(self.filter.width() / 0.5) as i32,
                             f32::floor(self.filter.height() / 0.5) as i32);
        let x_range = (cmp::max(region.start.0 as i32 - filter_pixels.0, 0),
                       cmp::min(region.end.0 as i32 + filter_pixels.0, self.width as i32 - 1));
        let y_range = (cmp::max(region.start.1 as i32 - filter_pixels.1, 0),
                       cmp::min(region.end.1 as i32 + filter_pixels.1, self.height as i32 - 1));
        /*
        println!("Writing starting at {:?} with filter pixels = {:?}\n\tx_range = {:?}, y_range = {:?}",
                 region.start, filter_pixels, x_range, y_range);
         */
        let block_x_range = (x_range.0 / self.lock_size.0, x_range.1 / self.lock_size.0);
        let block_y_range = (y_range.0 / self.lock_size.1, y_range.1 / self.lock_size.1);
        //println!("\tBlock x range {:?}, y range {:?}", block_x_range, block_y_range);
        if x_range.1 - x_range.0 < 0 || y_range.1 - y_range.0 < 0 {
                return;
        }
        // Temporary storage for filtered samples so we can compute the filtered results for
        // the block we're writing too without having to get the lock
        let mut filtered_samples: Vec<_> = iter::repeat(Colorf::broadcast(0.0))
            .take((self.lock_size.0 * self.lock_size.1) as usize).collect();

        let blocks_per_row = self.width as i32 / self.lock_size.0;
        for y in block_y_range.0..block_y_range.1 + 1 {
            for x in block_x_range.0..block_x_range.1 + 1 {
                //println!("\tBlock [{}, {}] is index {}", x, y, y * blocks_per_row + x);
                let x_write_range = (cmp::max(x_range.0, x * self.lock_size.0),
                                     cmp::min(x_range.1 + 1, x * self.lock_size.0 + self.lock_size.0));
                let y_write_range = (cmp::max(y_range.0, y * self.lock_size.1),
                                     cmp::min(y_range.1 + 1, y * self.lock_size.1 + self.lock_size.1));
                //println!("\tWriting to pixels x range: {:?}, y range {:?}", x_write_range, y_write_range);
                let block_samples = samples.iter().filter(|s| {
                    s.x >= (x_write_range.0 - filter_pixels.0) as f32
                        && s.x < (x_write_range.1 + filter_pixels.0) as f32
                        && s.y >= (y_write_range.0 - filter_pixels.1) as f32
                        && s.y < (y_write_range.1 + filter_pixels.1) as f32
                });

                for c in &mut filtered_samples {
                    *c = Colorf::broadcast(0.0);
                }

                // Compute the filtered samples for the block
                for c in block_samples {
                    let img_x = c.x - 0.5;
                    let img_y = c.y - 0.5;
                    for iy in y_write_range.0..y_write_range.1 {
                        let fy = f32::abs(iy as f32 - img_y) * self.filter.inv_height()
                            * FILTER_TABLE_SIZE as f32;
                        let fy_idx = cmp::min(fy as usize, FILTER_TABLE_SIZE - 1);
                        for ix in x_write_range.0..x_write_range.1 {
                            let fx = f32::abs(ix as f32 - img_x) * self.filter.inv_width()
                                * FILTER_TABLE_SIZE as f32;
                            let fx_idx = cmp::min(fx as usize, FILTER_TABLE_SIZE - 1);
                            let weight = self.filter_table[fy_idx * FILTER_TABLE_SIZE + fx_idx];
                            let px = ((iy - y * self.lock_size.0) * self.lock_size.0 + ix - x * self.lock_size.0) as usize;
                            // TODO: Can't currently overload the += operator
                            // Coming soon though, see RFC #953 https://github.com/rust-lang/rfcs/pull/953
                            filtered_samples[px].r += weight * c.color.r;
                            filtered_samples[px].g += weight * c.color.g;
                            filtered_samples[px].b += weight * c.color.b;
                            filtered_samples[px].a += weight;
                        }
                    }
                }

                // Acquire lock for the block and write the samples
                let block_idx = (y * blocks_per_row + x) as usize;
                let mut pixels = self.pixels_locked[block_idx].lock().unwrap();
                for iy in y_write_range.0..y_write_range.1 {
                    for ix in x_write_range.0..x_write_range.1 {
                        let px = ((iy - y * self.lock_size.0) * self.lock_size.0 + ix - x * self.lock_size.0) as usize;
                        let c = &filtered_samples[px];
                        pixels[px].r += c.r;
                        pixels[px].g += c.g;
                        pixels[px].b += c.b;
                        pixels[px].a += c.a;
                    }
                }
            }
        }
    }
    /// Clear the render target to black
    pub fn clear(&mut self) {
        for p in self.pixels.iter_mut() {
            *p = Colorf::broadcast(0.0);
        }
    }
    /// Get the dimensions of the render target
    pub fn dimensions(&self) -> (usize, usize) {
        (self.width, self.height)
    }
    /// Convert the floating point color buffer to 24bpp sRGB for output to an image
    pub fn get_render(&self) -> Vec<u8> {
        let mut render: Vec<u8> = iter::repeat(0u8).take(self.width * self.height * 3).collect();
        let x_blocks = self.width / self.lock_size.0 as usize;
        let y_blocks = self.height / self.lock_size.1 as usize;
        for by in 0..y_blocks {
            for bx in 0..x_blocks {
                let block_idx = (by * x_blocks + bx) as usize;
                let pixels = self.pixels_locked[block_idx].lock().unwrap();
                for y in 0..self.lock_size.1 as usize {
                    for x in 0..self.lock_size.0 as usize {
                        let c = &pixels[y * self.lock_size.0 as usize+ x];
                        if c.a > 0.0 {
                            let cn = (*c / c.a).clamp().to_srgb();
                            let px = (y + by * self.lock_size.0 as usize) * self.width * 3
                                    + (x + bx * self.lock_size.0 as usize) * 3;
                            for i in 0..3 {
                                render[px + i] = (cn[i] * 255.0) as u8;
                            }
                        }
                    }
                }
            }
        }
        render
    }
}

<|endoftext|>


<commit_before>#[repr(i32)]
pub enum ClusterFlags {
  Forwards = 0,
  Backwards = 1
}

<commit_msg>Copied documentation from Cairo for font cluster flags<commit_after>//! Describe font cluster flags

///  Specifies properties of a text cluster mapping.
///
/// Since 1.8
#[repr(i32)]
pub enum ClusterFlags {
  /// The clusters in the cluster array map to glyphs in the glyph array from start to end.
  Forwards = 0,
  /// The clusters in the cluster array map to glyphs in the glyph array from end to start. (Since 1.8)
  Backwards = 1
}

<|endoftext|>