<commit_before>use common::context::*;
use common::scheduler::*;

use graphics::bmp::*;

use programs::common::*;
use programs::editor::*;
use programs::executor::*;
use programs::filemanager::*;
use programs::viewer::*;

pub struct Session {
    pub display: Display,
    pub background: BMP,
    pub cursor: BMP,
    pub icon: BMP,
    pub mouse_point: Point,
    last_mouse_event: MouseEvent,
    pub items: Vec<Box<SessionItem>>,
    pub windows: Vec<*mut Window>,
    pub windows_ordered: Vec<*mut Window>,
    pub redraw: usize
}

impl Session {
    pub fn new() -> Session {
        unsafe {
            Session {
                display: Display::root(),
                background: BMP::new(),
                cursor: BMP::new(),
                icon: BMP::new(),
                mouse_point: Point::new(0, 0),
                last_mouse_event: MouseEvent {
                    x: 0,
                    y: 0,
                    left_button: false,
                    middle_button: false,
                    right_button: false,
                    valid: false
                },
                items: Vec::new(),
                windows: Vec::new(),
                windows_ordered: Vec::new(),
                redraw: REDRAW_ALL
            }
        }
    }

    pub unsafe fn add_window(&mut self, add_window_ptr: *mut Window){
        self.windows.push(add_window_ptr);
        self.windows_ordered.push(add_window_ptr);
        self.redraw = max(self.redraw, REDRAW_ALL);
    }

    pub unsafe fn remove_window(&mut self, remove_window_ptr: *mut Window){
        let mut i = 0;
        while i < self.windows.len() {
            let mut remove = false;

            match self.windows.get(i) {
                Option::Some(window_ptr) => if *window_ptr == remove_window_ptr {
                    remove = true;
                }else{
                    i += 1;
                },
                Option::None => break
            }

            if remove {
                self.windows.remove(i);
                self.redraw = max(self.redraw, REDRAW_ALL);
            }
        }

        i = 0;
        while i < self.windows_ordered.len() {
            let mut remove = false;

            match self.windows_ordered.get(i) {
                Option::Some(window_ptr) => if *window_ptr == remove_window_ptr {
                    remove = true;
                }else{
                    i += 1;
                },
                Option::None => break
            }

            if remove {
                self.windows_ordered.remove(i);
                self.redraw = max(self.redraw, REDRAW_ALL);
            }
        }
    }

    pub unsafe fn on_irq(&mut self, irq: u8){
        for item in self.items.iter() {
            let reenable = start_no_ints();
            item.on_irq(irq);
            end_no_ints(reenable);
        }
    }

    pub unsafe fn on_poll(&mut self){
        for item in self.items.iter() {
            let reenable = start_no_ints();
            item.on_poll();
            end_no_ints(reenable);
        }
    }

    pub fn open(&self, url: &URL) -> Box<Resource>{
        if url.scheme().len() == 0 {
            let mut list = String::new();

            for item in self.items.iter() {
                let scheme = item.scheme();
                if scheme.len() > 0 {
                    if list.len() > 0 {
                        list = list + "\n" + scheme;
                    }else{
                        list = scheme;
                    }
                }
            }

            return box VecResource::new(URL::new(), ResourceType::Dir, list.to_utf8());
        }else{
            for item in self.items.iter() {
                if item.scheme() == url.scheme() {
                    return item.open(url);
                }
            }
            return box NoneResource;
        }
    }

    fn item_main(&mut self, mut item: Box<SessionItem>, url: URL){
        Context::spawn(box move ||{
            item.main(url);
        });
    }

    fn on_key(&mut self, key_event: KeyEvent){
        if self.windows.len() > 0 {
            match self.windows.get(self.windows.len() - 1){
                Option::Some(window_ptr) => {
                    unsafe{
                        (**window_ptr).on_key(key_event);
                        self.redraw = max(self.redraw, REDRAW_ALL);
                    }
                },
                Option::None => ()
            }
        }
    }

    fn on_mouse(&mut self, mouse_event: MouseEvent){
        let mut catcher = -1;
        for reverse_i in 0..self.windows.len() {
            let i = self.windows.len() - 1 - reverse_i;
            match self.windows.get(i){
                Option::Some(window_ptr) => unsafe{
                    if (**window_ptr).on_mouse(mouse_event, catcher < 0) {
                        catcher = i as isize;

                        self.redraw = max(self.redraw, REDRAW_ALL);
                    }
                },
                Option::None => ()
            }
        }

        //Not caught, can be caught by task bar
        if catcher < 0 {
            if mouse_event.left_button &&  !self.last_mouse_event.left_button && mouse_event.y >= self.display.height as isize - 32 {
                if mouse_event.x <= 56 {
                    self.item_main(box FileManager::new(), URL::from_string(&"file:///".to_string()));
                }else{
                    for i in 0..self.windows_ordered.len() {
                        let chars = 16;
                        let x = 5*8 + 2*8 + (chars*8 + 3*8) * i as isize;
                        let w = chars*8 + 2*8;
                        if mouse_event.x >= x && mouse_event.x < x + w {
                            match self.windows_ordered.get(i) {
                                Option::Some(window_ptr) => unsafe {
                                    for j in 0..self.windows.len() {
                                        match self.windows.get(j){
                                            Option::Some(catcher_window_ptr) => if catcher_window_ptr == window_ptr {
                                                if j == self.windows.len() - 1 {
                                                    (**window_ptr).minimized = !(**window_ptr).minimized;
                                                }else{
                                                    catcher = j as isize;
                                                    (**window_ptr).minimized = false;
                                                }
                                                break;
                                            },
                                            Option::None => break
                                        }
                                    }
                                    self.redraw = max(self.redraw, REDRAW_ALL);
                                },
                                Option::None => ()
                            }
                            break;
                        }
                    }
                }
            }
        }

        if catcher >= 0 && catcher < self.windows.len() as isize - 1 {
            match self.windows.remove(catcher as usize){
                Option::Some(window_ptr) => self.windows.push(window_ptr),
                Option::None => ()
            }
        }

        self.last_mouse_event = mouse_event;
    }

    pub unsafe fn redraw(&mut self){
        if self.redraw > REDRAW_NONE {
            if self.redraw >= REDRAW_ALL {
                self.display.set(Color::new(64, 64, 64));
                if self.background.data > 0 {
                    self.display.image(Point::new((self.display.width as isize - self.background.size.width as isize)/2, (self.display.height as isize - self.background.size.height as isize)/2), self.background.data, self.background.size);
                }

                for i in 0..self.windows.len(){
                    match self.windows.get(i) {
                        Option::Some(window_ptr) => {
                            (**window_ptr).focused = i == self.windows.len() - 1;
                            (**window_ptr).draw(&self.display);
                        },
                        Option::None => ()
                    }
                }

                self.display.rect(Point::new(0, self.display.height as isize - 32), Size::new(self.display.width, 32), Color::new(0, 0, 0));
                if self.icon.data > 0 {
                    self.display.image_alpha(Point::new(12, self.display.height as isize - 32), self.icon.data, self.icon.size);
                }else{
                    self.display.text(Point::new(8, self.display.height as isize - 24), &String::from_str("Redox"), Color::new(255, 255, 255));
                }

                for i in 0..self.windows_ordered.len() {
                    match self.windows_ordered.get(i) {
                        Option::Some(window_ptr) => {
                            let chars = 16;
                            let x = 5*8 + 2*8 + (chars*8 + 3*8) * i as isize;
                            let w = chars*8 + 2*8;
                            self.display.rect(Point::new(x, self.display.height as isize - 32), Size::new(w as usize, 32), (**window_ptr).border_color);
                            self.display.text(Point::new(x + 8, self.display.height as isize - 24), &(**window_ptr).title.substr(0, chars as usize), (**window_ptr).title_color);
                        },
                        Option::None => ()
                    }
                }
            }

            let reenable = start_no_ints();

            self.display.flip();

            if self.cursor.data > 0 {
                self.display.image_alpha_onscreen(self.mouse_point, self.cursor.data, self.cursor.size);
            }else{
                self.display.char_onscreen(Point::new(self.mouse_point.x - 3, self.mouse_point.y - 9), 'X', Color::new(255, 255, 255));
            }

            self.redraw = REDRAW_NONE;

            end_no_ints(reenable);
        }
    }

    pub fn event(&mut self, event: Event){
        match event.to_option() {
            EventOption::Mouse(mouse_event) => self.on_mouse(mouse_event),
            EventOption::Key(key_event) => self.on_key(key_event),
            EventOption::Redraw(redraw_event) => self.redraw = max(self.redraw, redraw_event.redraw),
            EventOption::Open(open_event) => {
                let url_string = open_event.url_string;
                let url = URL::from_string(&url_string);

                if url_string.ends_with(".md".to_string()) || url_string.ends_with(".rs".to_string()) || url_string.ends_with(".sh".to_string()){
                    self.item_main(box Editor::new(), url);
                }else if url_string.ends_with(".bin".to_string()){
                    self.item_main(box Executor::new(), url);
                }else if url_string.ends_with(".bmp".to_string()){
                    self.item_main(box Viewer::new(), url);
                }else{
                    d("No program found: ");
                    url.d();
                    dl();
                }
            }
            _ => ()
        }
    }
}
<commit_msg>Modify size of taskbar items<commit_after>use common::context::*;
use common::scheduler::*;

use graphics::bmp::*;

use programs::common::*;
use programs::editor::*;
use programs::executor::*;
use programs::filemanager::*;
use programs::viewer::*;

pub struct Session {
    pub display: Display,
    pub background: BMP,
    pub cursor: BMP,
    pub icon: BMP,
    pub mouse_point: Point,
    last_mouse_event: MouseEvent,
    pub items: Vec<Box<SessionItem>>,
    pub windows: Vec<*mut Window>,
    pub windows_ordered: Vec<*mut Window>,
    pub redraw: usize
}

impl Session {
    pub fn new() -> Session {
        unsafe {
            Session {
                display: Display::root(),
                background: BMP::new(),
                cursor: BMP::new(),
                icon: BMP::new(),
                mouse_point: Point::new(0, 0),
                last_mouse_event: MouseEvent {
                    x: 0,
                    y: 0,
                    left_button: false,
                    middle_button: false,
                    right_button: false,
                    valid: false
                },
                items: Vec::new(),
                windows: Vec::new(),
                windows_ordered: Vec::new(),
                redraw: REDRAW_ALL
            }
        }
    }

    pub unsafe fn add_window(&mut self, add_window_ptr: *mut Window){
        self.windows.push(add_window_ptr);
        self.windows_ordered.push(add_window_ptr);
        self.redraw = max(self.redraw, REDRAW_ALL);
    }

    pub unsafe fn remove_window(&mut self, remove_window_ptr: *mut Window){
        let mut i = 0;
        while i < self.windows.len() {
            let mut remove = false;

            match self.windows.get(i) {
                Option::Some(window_ptr) => if *window_ptr == remove_window_ptr {
                    remove = true;
                }else{
                    i += 1;
                },
                Option::None => break
            }

            if remove {
                self.windows.remove(i);
                self.redraw = max(self.redraw, REDRAW_ALL);
            }
        }

        i = 0;
        while i < self.windows_ordered.len() {
            let mut remove = false;

            match self.windows_ordered.get(i) {
                Option::Some(window_ptr) => if *window_ptr == remove_window_ptr {
                    remove = true;
                }else{
                    i += 1;
                },
                Option::None => break
            }

            if remove {
                self.windows_ordered.remove(i);
                self.redraw = max(self.redraw, REDRAW_ALL);
            }
        }
    }

    pub unsafe fn on_irq(&mut self, irq: u8){
        for item in self.items.iter() {
            let reenable = start_no_ints();
            item.on_irq(irq);
            end_no_ints(reenable);
        }
    }

    pub unsafe fn on_poll(&mut self){
        for item in self.items.iter() {
            let reenable = start_no_ints();
            item.on_poll();
            end_no_ints(reenable);
        }
    }

    pub fn open(&self, url: &URL) -> Box<Resource>{
        if url.scheme().len() == 0 {
            let mut list = String::new();

            for item in self.items.iter() {
                let scheme = item.scheme();
                if scheme.len() > 0 {
                    if list.len() > 0 {
                        list = list + "\n" + scheme;
                    }else{
                        list = scheme;
                    }
                }
            }

            return box VecResource::new(URL::new(), ResourceType::Dir, list.to_utf8());
        }else{
            for item in self.items.iter() {
                if item.scheme() == url.scheme() {
                    return item.open(url);
                }
            }
            return box NoneResource;
        }
    }

    fn item_main(&mut self, mut item: Box<SessionItem>, url: URL){
        Context::spawn(box move ||{
            item.main(url);
        });
    }

    fn on_key(&mut self, key_event: KeyEvent){
        if self.windows.len() > 0 {
            match self.windows.get(self.windows.len() - 1){
                Option::Some(window_ptr) => {
                    unsafe{
                        (**window_ptr).on_key(key_event);
                        self.redraw = max(self.redraw, REDRAW_ALL);
                    }
                },
                Option::None => ()
            }
        }
    }

    fn on_mouse(&mut self, mouse_event: MouseEvent){
        let mut catcher = -1;
        for reverse_i in 0..self.windows.len() {
            let i = self.windows.len() - 1 - reverse_i;
            match self.windows.get(i){
                Option::Some(window_ptr) => unsafe{
                    if (**window_ptr).on_mouse(mouse_event, catcher < 0) {
                        catcher = i as isize;

                        self.redraw = max(self.redraw, REDRAW_ALL);
                    }
                },
                Option::None => ()
            }
        }

        //Not caught, can be caught by task bar
        if catcher < 0 {
            if mouse_event.left_button &&  !self.last_mouse_event.left_button && mouse_event.y >= self.display.height as isize - 32 {
                if mouse_event.x <= 56 {
                    self.item_main(box FileManager::new(), URL::from_string(&"file:///".to_string()));
                }else{
                    let mut chars = 32;
                    while chars > 4 && (chars*8 + 3*4) * self.windows.len() > self.display.width {
                        chars -= 1;
                    }

                    for i in 0..self.windows_ordered.len() {
                        let x = (5*8 + 2*8 + (chars*8 + 3*4) * i) as isize;
                        let w = (chars*8 + 2*4) as usize;
                        if mouse_event.x >= x && mouse_event.x < x + w as isize {
                            match self.windows_ordered.get(i) {
                                Option::Some(window_ptr) => unsafe {
                                    for j in 0..self.windows.len() {
                                        match self.windows.get(j){
                                            Option::Some(catcher_window_ptr) => if catcher_window_ptr == window_ptr {
                                                if j == self.windows.len() - 1 {
                                                    (**window_ptr).minimized = !(**window_ptr).minimized;
                                                }else{
                                                    catcher = j as isize;
                                                    (**window_ptr).minimized = false;
                                                }
                                                break;
                                            },
                                            Option::None => break
                                        }
                                    }
                                    self.redraw = max(self.redraw, REDRAW_ALL);
                                },
                                Option::None => ()
                            }
                            break;
                        }
                    }
                }
            }
        }

        if catcher >= 0 && catcher < self.windows.len() as isize - 1 {
            match self.windows.remove(catcher as usize){
                Option::Some(window_ptr) => self.windows.push(window_ptr),
                Option::None => ()
            }
        }

        self.last_mouse_event = mouse_event;
    }

    pub unsafe fn redraw(&mut self){
        if self.redraw > REDRAW_NONE {
            if self.redraw >= REDRAW_ALL {
                self.display.set(Color::new(64, 64, 64));
                if self.background.data > 0 {
                    self.display.image(Point::new((self.display.width as isize - self.background.size.width as isize)/2, (self.display.height as isize - self.background.size.height as isize)/2), self.background.data, self.background.size);
                }

                for i in 0..self.windows.len(){
                    match self.windows.get(i) {
                        Option::Some(window_ptr) => {
                            (**window_ptr).focused = i == self.windows.len() - 1;
                            (**window_ptr).draw(&self.display);
                        },
                        Option::None => ()
                    }
                }

                self.display.rect(Point::new(0, self.display.height as isize - 32), Size::new(self.display.width, 32), Color::new(0, 0, 0));
                if self.icon.data > 0 {
                    self.display.image_alpha(Point::new(12, self.display.height as isize - 32), self.icon.data, self.icon.size);
                }else{
                    self.display.text(Point::new(8, self.display.height as isize - 24), &String::from_str("Redox"), Color::new(255, 255, 255));
                }

                let mut chars = 32;
                while chars > 4 && (chars*8 + 3*4) * self.windows.len() > self.display.width {
                    chars -= 1;
                }

                for i in 0..self.windows_ordered.len() {
                    match self.windows_ordered.get(i) {
                        Option::Some(window_ptr) => {
                            let x = (5*8 + 2*8 + (chars*8 + 3*4) * i) as isize;
                            let w = (chars*8 + 2*4) as usize;
                            self.display.rect(Point::new(x, self.display.height as isize - 32), Size::new(w, 32), (**window_ptr).border_color);
                            self.display.text(Point::new(x + 4, self.display.height as isize - 24), &(**window_ptr).title.substr(0, chars as usize), (**window_ptr).title_color);
                        },
                        Option::None => ()
                    }
                }
            }

            let reenable = start_no_ints();

            self.display.flip();

            if self.cursor.data > 0 {
                self.display.image_alpha_onscreen(self.mouse_point, self.cursor.data, self.cursor.size);
            }else{
                self.display.char_onscreen(Point::new(self.mouse_point.x - 3, self.mouse_point.y - 9), 'X', Color::new(255, 255, 255));
            }

            self.redraw = REDRAW_NONE;

            end_no_ints(reenable);
        }
    }

    pub fn event(&mut self, event: Event){
        match event.to_option() {
            EventOption::Mouse(mouse_event) => self.on_mouse(mouse_event),
            EventOption::Key(key_event) => self.on_key(key_event),
            EventOption::Redraw(redraw_event) => self.redraw = max(self.redraw, redraw_event.redraw),
            EventOption::Open(open_event) => {
                let url_string = open_event.url_string;
                let url = URL::from_string(&url_string);

                if url_string.ends_with(".md".to_string()) || url_string.ends_with(".rs".to_string()) || url_string.ends_with(".sh".to_string()){
                    self.item_main(box Editor::new(), url);
                }else if url_string.ends_with(".bin".to_string()){
                    self.item_main(box Executor::new(), url);
                }else if url_string.ends_with(".bmp".to_string()){
                    self.item_main(box Viewer::new(), url);
                }else{
                    d("No program found: ");
                    url.d();
                    dl();
                }
            }
            _ => ()
        }
    }
}
<|endoftext|>


<commit_before>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use decoders::ljpeg::*;
use decoders::cfa::*;
use std::f32::NAN;
use std::cmp;

#[derive(Debug, Clone)]
pub struct DngDecoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> DngDecoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> DngDecoder<'a> {
    DngDecoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for DngDecoder<'a> {
  fn image(&self) -> Result<Image,String> {
    let ifds = self.tiff.find_ifds_with_tag(Tag::Compression).into_iter().filter(|ifd| {
      let compression = (**ifd).find_entry(Tag::Compression).unwrap().get_u32(0);
      let subsampled = match (**ifd).find_entry(Tag::NewSubFileType) {
        Some(e) => e.get_u32(0) & 1 != 0,
        None => false,
      };
      !subsampled && (compression == 7 || compression == 1 || compression == 0x884c)
    }).collect::<Vec<&TiffIFD>>();
    let raw = ifds[0];
    let width = fetch_tag!(raw, Tag::ImageWidth).get_u32(0);
    let height = fetch_tag!(raw, Tag::ImageLength).get_u32(0);

    let image = match fetch_tag!(raw, Tag::Compression).get_u32(0) {
      1 => try!(self.decode_uncompressed(raw, width as usize, height as usize)),
      7 => try!(self.decode_compressed(raw, width as usize, height as usize)),
      c => return Err(format!("Don't know how to read DNGs with compression {}", c).to_string()),
    };

    let (make, model, canonical_make, canonical_model) = {
      match self.rawloader.check_supported(&self.tiff) {
        Ok(cam) => {
          (cam.make.clone(), cam.model.clone(),
           cam.canonical_make.clone(),cam.canonical_model.clone())
        },
        Err(_) => {
          let make = fetch_tag!(self.tiff, Tag::Make).get_str();
          let model = fetch_tag!(self.tiff, Tag::Model).get_str();
          (make.to_string(), model.to_string(), make.to_string(), model.to_string())
        },
      }
    };

    Ok(Image {
      make: make,
      model: model,
      canonical_make: canonical_make,
      canonical_model: canonical_model,
      width: width as usize,
      height: height as usize,
      wb_coeffs: try!(self.get_wb()),
      data: image.into_boxed_slice(),
      blacklevels: try!(self.get_blacklevels(raw)),
      whitelevels: try!(self.get_whitelevels(raw)),
      xyz_to_cam: try!(self.get_color_matrix()),
      cfa: try!(self.get_cfa(raw)),
      crops: try!(self.get_crops(raw, width as usize, height as usize)),
    })
  }
}

impl<'a> DngDecoder<'a> {
  fn get_wb(&self) -> Result<[f32;4], String> {
    let levels = fetch_tag!(self.tiff, Tag::AsShotNeutral);
    Ok([1.0/levels.get_f32(0),1.0/levels.get_f32(1),1.0/levels.get_f32(2),NAN])
  }

  fn get_blacklevels(&self, raw: &TiffIFD) -> Result<[u16;4], String> {
    let levels = fetch_tag!(raw, Tag::BlackLevels);
    Ok([levels.get_f32(0) as u16,levels.get_f32(1) as u16,
        levels.get_f32(2) as u16,levels.get_f32(3) as u16])
  }

  fn get_whitelevels(&self, raw: &TiffIFD) -> Result<[u16;4], String> {
    let level = fetch_tag!(raw, Tag::WhiteLevel).get_u32(0) as u16;
    Ok([level,level,level,level])
  }

  fn get_cfa(&self, raw: &TiffIFD) -> Result<CFA,String> {
    let pattern = fetch_tag!(raw, Tag::CFAPattern);
    Ok(CFA::new_from_tag(pattern))
  }

  fn get_crops(&self, raw: &TiffIFD, width: usize, height: usize) -> Result<[usize;4],String> {
    let crops = fetch_tag!(raw, Tag::ActiveArea);
    Ok([crops.get_u32(0) as usize, width - crops.get_u32(3) as usize,
        height - crops.get_u32(2) as usize, crops.get_u32(1) as usize])
  }

  fn get_color_matrix(&self) -> Result<[[f32;3];4],String> {
    let mut matrix: [[f32;3];4] = [[0.0;3];4];
    let cmatrix = fetch_tag!(self.tiff, Tag::ColorMatrix2);
    if cmatrix.count() > 12 {
      Err(format!("color matrix supposedly has {} components",cmatrix.count()).to_string())
    } else {
      for i in 0..(cmatrix.count() as usize) {
        matrix[i/3][i%3] = cmatrix.get_f32(i);
      }
      Ok(matrix)
    }
  }

  pub fn decode_uncompressed(&self, raw: &TiffIFD, width: usize, height: usize) -> Result<Vec<u16>,String> {
    let offset = fetch_tag!(raw, Tag::StripOffsets).get_u32(0) as usize;
    let src = &self.buffer[offset..];

    match fetch_tag!(raw, Tag::BitsPerSample).get_u32(0) {
      16  => Ok(decode_16le(src, width, height)),
      bps => Err(format!("DNG: Don't know about {} bps images", bps).to_string()),
    }
  }

  pub fn decode_compressed(&self, raw: &TiffIFD, width: usize, height: usize) -> Result<Vec<u16>,String> {
    if raw.has_entry(Tag::StripOffsets) { // We're in a normal offset situation
      let offsets = fetch_tag!(raw, Tag::StripOffsets);
      if offsets.count() != 1 {
        return Err("DNG: files with more than one slice not supported yet".to_string())
      }
      let offset = offsets.get_u32(0) as usize;
      let src = &self.buffer[offset..];
      let mut out = vec![0 as u16; width*height];
      let decompressor = try!(LjpegDecompressor::new(src, true));
      try!(decompressor.decode(&mut out, 0, width, width, height));
      Ok(out)
    } else if raw.has_entry(Tag::TileOffsets) { // They've gone with tiling
      let twidth = fetch_tag!(raw, Tag::TileWidth).get_u32(0) as usize;
      let tlength = fetch_tag!(raw, Tag::TileLength).get_u32(0) as usize;
      let offsets = fetch_tag!(raw, Tag::TileOffsets);
      let coltiles = (width-1)/twidth + 1;
      let rowtiles = (height-1)/tlength + 1;
      if coltiles*rowtiles != offsets.count() as usize {
        return Err(format!("DNG: trying to decode {} tiles from {} offsets",
                           coltiles*rowtiles, offsets.count()).to_string())
      }

      Ok(decode_threaded_multiline(width, height, tlength, &(|strip: &mut [u16], row| {
        let row = row / tlength;
        for col in 0..coltiles {
          let offset = offsets.get_u32(row*coltiles+col) as usize;
          let src = &self.buffer[offset..];
          // We don't use bigtable here as the tiles are two small to amortize the setup cost
          let decompressor = LjpegDecompressor::new(src, true).unwrap();
          let bwidth = cmp::min(width, (col+1)*twidth) - col*twidth;
          let blength = cmp::min(height, (row+1)*tlength) - row*tlength;
          decompressor.decode(strip, col*twidth, width, bwidth, blength).unwrap();
        }
      })))
    } else {
      Err("DNG: didn't find tiles or strips".to_string())
    }
  }
}
<commit_msg>DNG: default to no crop with no ActiveArea<commit_after>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use decoders::ljpeg::*;
use decoders::cfa::*;
use std::f32::NAN;
use std::cmp;

#[derive(Debug, Clone)]
pub struct DngDecoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> DngDecoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> DngDecoder<'a> {
    DngDecoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for DngDecoder<'a> {
  fn image(&self) -> Result<Image,String> {
    let ifds = self.tiff.find_ifds_with_tag(Tag::Compression).into_iter().filter(|ifd| {
      let compression = (**ifd).find_entry(Tag::Compression).unwrap().get_u32(0);
      let subsampled = match (**ifd).find_entry(Tag::NewSubFileType) {
        Some(e) => e.get_u32(0) & 1 != 0,
        None => false,
      };
      !subsampled && (compression == 7 || compression == 1 || compression == 0x884c)
    }).collect::<Vec<&TiffIFD>>();
    let raw = ifds[0];
    let width = fetch_tag!(raw, Tag::ImageWidth).get_u32(0);
    let height = fetch_tag!(raw, Tag::ImageLength).get_u32(0);

    let image = match fetch_tag!(raw, Tag::Compression).get_u32(0) {
      1 => try!(self.decode_uncompressed(raw, width as usize, height as usize)),
      7 => try!(self.decode_compressed(raw, width as usize, height as usize)),
      c => return Err(format!("Don't know how to read DNGs with compression {}", c).to_string()),
    };

    let (make, model, canonical_make, canonical_model) = {
      match self.rawloader.check_supported(&self.tiff) {
        Ok(cam) => {
          (cam.make.clone(), cam.model.clone(),
           cam.canonical_make.clone(),cam.canonical_model.clone())
        },
        Err(_) => {
          let make = fetch_tag!(self.tiff, Tag::Make).get_str();
          let model = fetch_tag!(self.tiff, Tag::Model).get_str();
          (make.to_string(), model.to_string(), make.to_string(), model.to_string())
        },
      }
    };

    Ok(Image {
      make: make,
      model: model,
      canonical_make: canonical_make,
      canonical_model: canonical_model,
      width: width as usize,
      height: height as usize,
      wb_coeffs: try!(self.get_wb()),
      data: image.into_boxed_slice(),
      blacklevels: try!(self.get_blacklevels(raw)),
      whitelevels: try!(self.get_whitelevels(raw)),
      xyz_to_cam: try!(self.get_color_matrix()),
      cfa: try!(self.get_cfa(raw)),
      crops: try!(self.get_crops(raw, width as usize, height as usize)),
    })
  }
}

impl<'a> DngDecoder<'a> {
  fn get_wb(&self) -> Result<[f32;4], String> {
    let levels = fetch_tag!(self.tiff, Tag::AsShotNeutral);
    Ok([1.0/levels.get_f32(0),1.0/levels.get_f32(1),1.0/levels.get_f32(2),NAN])
  }

  fn get_blacklevels(&self, raw: &TiffIFD) -> Result<[u16;4], String> {
    let levels = fetch_tag!(raw, Tag::BlackLevels);
    Ok([levels.get_f32(0) as u16,levels.get_f32(1) as u16,
        levels.get_f32(2) as u16,levels.get_f32(3) as u16])
  }

  fn get_whitelevels(&self, raw: &TiffIFD) -> Result<[u16;4], String> {
    let level = fetch_tag!(raw, Tag::WhiteLevel).get_u32(0) as u16;
    Ok([level,level,level,level])
  }

  fn get_cfa(&self, raw: &TiffIFD) -> Result<CFA,String> {
    let pattern = fetch_tag!(raw, Tag::CFAPattern);
    Ok(CFA::new_from_tag(pattern))
  }

  fn get_crops(&self, raw: &TiffIFD, width: usize, height: usize) -> Result<[usize;4],String> {
    if raw.has_entry(Tag::ActiveArea) {
      let crops = fetch_tag!(raw, Tag::ActiveArea);
      Ok([crops.get_u32(0) as usize, width - crops.get_u32(3) as usize,
          height - crops.get_u32(2) as usize, crops.get_u32(1) as usize])
    } else {
      // Ignore missing crops, at least some pentax DNGs don't have it
      Ok([0,0,0,0])
    }
  }

  fn get_color_matrix(&self) -> Result<[[f32;3];4],String> {
    let mut matrix: [[f32;3];4] = [[0.0;3];4];
    let cmatrix = fetch_tag!(self.tiff, Tag::ColorMatrix2);
    if cmatrix.count() > 12 {
      Err(format!("color matrix supposedly has {} components",cmatrix.count()).to_string())
    } else {
      for i in 0..(cmatrix.count() as usize) {
        matrix[i/3][i%3] = cmatrix.get_f32(i);
      }
      Ok(matrix)
    }
  }

  pub fn decode_uncompressed(&self, raw: &TiffIFD, width: usize, height: usize) -> Result<Vec<u16>,String> {
    let offset = fetch_tag!(raw, Tag::StripOffsets).get_u32(0) as usize;
    let src = &self.buffer[offset..];

    match fetch_tag!(raw, Tag::BitsPerSample).get_u32(0) {
      16  => Ok(decode_16le(src, width, height)),
      bps => Err(format!("DNG: Don't know about {} bps images", bps).to_string()),
    }
  }

  pub fn decode_compressed(&self, raw: &TiffIFD, width: usize, height: usize) -> Result<Vec<u16>,String> {
    if raw.has_entry(Tag::StripOffsets) { // We're in a normal offset situation
      let offsets = fetch_tag!(raw, Tag::StripOffsets);
      if offsets.count() != 1 {
        return Err("DNG: files with more than one slice not supported yet".to_string())
      }
      let offset = offsets.get_u32(0) as usize;
      let src = &self.buffer[offset..];
      let mut out = vec![0 as u16; width*height];
      let decompressor = try!(LjpegDecompressor::new(src, true));
      try!(decompressor.decode(&mut out, 0, width, width, height));
      Ok(out)
    } else if raw.has_entry(Tag::TileOffsets) { // They've gone with tiling
      let twidth = fetch_tag!(raw, Tag::TileWidth).get_u32(0) as usize;
      let tlength = fetch_tag!(raw, Tag::TileLength).get_u32(0) as usize;
      let offsets = fetch_tag!(raw, Tag::TileOffsets);
      let coltiles = (width-1)/twidth + 1;
      let rowtiles = (height-1)/tlength + 1;
      if coltiles*rowtiles != offsets.count() as usize {
        return Err(format!("DNG: trying to decode {} tiles from {} offsets",
                           coltiles*rowtiles, offsets.count()).to_string())
      }

      Ok(decode_threaded_multiline(width, height, tlength, &(|strip: &mut [u16], row| {
        let row = row / tlength;
        for col in 0..coltiles {
          let offset = offsets.get_u32(row*coltiles+col) as usize;
          let src = &self.buffer[offset..];
          // We don't use bigtable here as the tiles are two small to amortize the setup cost
          let decompressor = LjpegDecompressor::new(src, true).unwrap();
          let bwidth = cmp::min(width, (col+1)*twidth) - col*twidth;
          let blength = cmp::min(height, (row+1)*tlength) - row*tlength;
          decompressor.decode(strip, col*twidth, width, bwidth, blength).unwrap();
        }
      })))
    } else {
      Err("DNG: didn't find tiles or strips".to_string())
    }
  }
}
<|endoftext|>


<commit_before>use std::num::Float;
use std::slice::Iter;
use geometry::bbox::get_bounds_from_objects;
use geometry::{BBox, Prim};
use raytracer::Ray;
use vec3::Vec3;

pub struct Octree<T> {
    pub prims: Option<Vec<T>>,
    pub bbox: BBox,
    pub depth: isize,
    pub children: Vec<Octree<T>>,
    pub data: Vec<OctreeData>,
    pub infinites: Vec<T> // for infinite prims (planes)
}

#[derive(Clone, Copy)]
struct OctreeData {
    pub bbox: Option<BBox>,
    pub index: usize
}

impl OctreeData {
    pub fn intersects(&self, ray: &Ray) -> bool {
        match self.bbox {
            Some(bbox) => bbox.intersects(ray),
            None => true
        }
    }
}

impl<T> Octree<T> {
    #[allow(dead_code)]
    pub fn new(bbox: BBox, depth: isize) -> Octree<T> {
        let vec_children: Vec<Octree<T>> = Vec::new();
        let vec_data: Vec<OctreeData> = Vec::new();
        let vec_infinite_data: Vec<T> = Vec::new();

        Octree {
            prims: None,
            bbox: bbox,
            depth: depth,
            children: vec_children,
            data: vec_data,
            infinites: vec_infinite_data
        }
    }

    fn subdivide(&mut self) {
        for x in range(0is, 2is) {
            for y in range(0is, 2is) {
                for z in range(0is, 2is) {
                    let len = self.bbox.len();

                    let child_bbox = BBox {
                        min: Vec3 {
                            x: self.bbox.min.x + x as f64 * len.x / 2.0,
                            y: self.bbox.min.y + y as f64 * len.y / 2.0,
                            z: self.bbox.min.z + z as f64 * len.z / 2.0
                        },
                        max: Vec3 {
                            x: self.bbox.max.x - (1 - x) as f64 * len.x / 2.0,
                            y: self.bbox.max.y - (1 - y) as f64 * len.y / 2.0,
                            z: self.bbox.max.z - (1 - z) as f64 * len.z / 2.0,
                        }
                    };

                    self.children.push(Octree::new(child_bbox, self.depth - 1));
                }
            }
        }
    }

    #[allow(dead_code)]
    pub fn insert(&mut self, index: usize, object_bbox: Option<BBox>) -> () {
        match object_bbox {
            // Finite object
            Some(object_bbox) => {
                // Max depth
                if self.depth <= 0 {
                    self.data.push(OctreeData { index: index, bbox: Some(object_bbox) });
                    return;
                }

                // Empty leaf node
                if self.is_leaf() && self.data.len() == 0 {
                    self.data.push(OctreeData { index: index, bbox: Some(object_bbox) });
                    return;
                }

                // Occupied leaf node and not max depth: subdivide node
                if self.is_leaf() && self.data.len() == 1 {
                    self.subdivide();
                    let old = self.data.remove(0);
                    // Reinsert old node and then fall through to insert current object
                    self.insert(old.index, old.bbox);
                }

                // Interior node (has children)
                for child in self.children.iter_mut() {
                    if child.bbox.overlaps(&object_bbox) {
                        child.insert(index, Some(object_bbox));
                    }
                }
            }

            // Infinite object without bounds, this is added to
            // all get_intersection_indices calls
            None => panic!("Don't push infinites this way")
        }
    }

    fn is_leaf(&self) -> bool {
        self.children.len() == 0
    }
}

// TODO: sell: Prims can later implement a Bounded3D trait containing a method
//             that returns Option<BBox>.  Some if finite, None if infinite.
//             Then we can use impl<T: Bounded3D> Octree<Box<T>>, probably!

impl Octree<Box<Prim+Send+Sync>> {
    #[allow(dead_code)]
    pub fn new_from_prims(prims: Vec<Box<Prim+Send+Sync>>) -> Octree<Box<Prim+Send+Sync>> {
        let bounds = get_bounds_from_objects(&prims);
        let (finites, infinites): (Vec<Box<Prim+Send+Sync>>, Vec<Box<Prim+Send+Sync>>) = prims.into_iter().partition(|prim| prim.bounding().is_some());
        // pbrt recommended max depth for a k-d tree (though, we're using an octree)
        // For a k-d tree: 8 + 1.3 * log2(N)
        let depth = (1.2 * (finites.len() as f64).log(8.0)).round() as isize;

        println!("Octree maximum depth {}", depth);
        let mut octree = Octree::new(bounds, depth);

        for (i, prim) in finites.iter().enumerate() {
            octree.insert(i, prim.bounding());
        }
        octree.prims = Some(finites);
        octree.infinites = infinites;

        octree
    }

    pub fn get_intersected_objects<'a>(&'a self, ray: &'a Ray) -> OctreeIterator<'a, Box<Prim+Send+Sync>> {
        OctreeIterator::new(self, ray)
    }
}

struct OctreeIterator<'a, T:'a> {
    prims: &'a Vec<T>,
    stack: Vec<&'a Octree<T>>,
    cur_iter: Option<Iter<'a, OctreeData>>,
    ray: &'a Ray,
    infinites: Iter<'a, T>,
    just_infinites: bool

}

impl<'a> OctreeIterator<'a, Box<Prim+Send+Sync>> {
    fn new<'b>(root: &'b Octree<Box<Prim+Send+Sync>>, ray: &'b Ray) -> OctreeIterator<'b, Box<Prim+Send+Sync>> {
        let prims = match root.prims {
            Some(ref prims) => prims,
            None => panic!("OctreeIterator must be constructed from an Octree root")
        };
        OctreeIterator {
            prims: prims,
            stack: vec![root],
            cur_iter: None,
            ray: ray,
            infinites: root.infinites.iter(),
            just_infinites: false
        }
    }
}

impl<'a> Iterator for OctreeIterator<'a, Box<Prim+Send+Sync>> {
    type Item = &'a Box<Prim+Send+Sync>;

    fn next(&mut self) -> Option<&'a Box<Prim+Send+Sync>> {
        if self.just_infinites {
            return self.infinites.next();
        }
        loop {
            let (new_cur_iter, val) = match self.cur_iter.take() {
                Some(mut cur_iter) => match cur_iter.next() {
                    Some(val) => (Some(cur_iter), Some(val)),
                    None => (None, None)
                },
                None => match self.stack.pop() {
                    Some(node) => {
                        for child in node.children.iter() {
                            if child.bbox.intersects(self.ray) {
                                self.stack.push(child);
                            }
                        }
                        (Some(node.data.iter()), None)
                    },
                    None => break  // Empty stack and no iterator
                }
            };
            self.cur_iter = new_cur_iter;
            match val {
                Some(val) => {
                    if val.intersects(self.ray) {
                        return Some(&self.prims[val.index]);
                    }
                },
                None => (),
            }
        }
        self.just_infinites = true;
        self.infinites.next()
    }
}
<commit_msg>Octree cleanup<commit_after>use std::num::Float;
use std::slice::Iter;
use geometry::bbox::get_bounds_from_objects;
use geometry::{BBox, Prim};
use raytracer::Ray;
use vec3::Vec3;

pub struct Octree<T> {
    prims: Vec<T>,
    infinites: Vec<T>, // for infinite prims (planes)
    root: OctreeNode<T>,
}

pub struct OctreeNode<T> {
    bbox: BBox,
    depth: i32,
    children: Vec<OctreeNode<T>>,
    leaf_data: Vec<OctreeData>,
}

#[derive(Clone, Copy)]
struct OctreeData {
    pub bbox: BBox,
    pub index: usize
}

impl OctreeData {
    pub fn intersects(&self, ray: &Ray) -> bool {
        self.bbox.intersects(ray)
    }
}

impl<T> OctreeNode<T> {
    #[allow(dead_code)]
    pub fn new(bbox: BBox, depth: i32) -> OctreeNode<T> {
        OctreeNode {
            bbox: bbox,
            depth: depth,
            children: Vec::new(),
            leaf_data: Vec::new(),
        }
    }

    fn subdivide(&mut self) {
        for x in range(0is, 2is) {
            for y in range(0is, 2is) {
                for z in range(0is, 2is) {
                    let len = self.bbox.len();

                    let child_bbox = BBox {
                        min: Vec3 {
                            x: self.bbox.min.x + x as f64 * len.x / 2.0,
                            y: self.bbox.min.y + y as f64 * len.y / 2.0,
                            z: self.bbox.min.z + z as f64 * len.z / 2.0
                        },
                        max: Vec3 {
                            x: self.bbox.max.x - (1 - x) as f64 * len.x / 2.0,
                            y: self.bbox.max.y - (1 - y) as f64 * len.y / 2.0,
                            z: self.bbox.max.z - (1 - z) as f64 * len.z / 2.0,
                        }
                    };

                    self.children.push(OctreeNode::new(child_bbox, self.depth - 1));
                }
            }
        }
    }

    #[allow(dead_code)]
    pub fn insert(&mut self, index: usize, object_bbox: BBox) -> () {
        // Max depth
        if self.depth <= 0 {
            self.leaf_data.push(OctreeData { index: index, bbox: object_bbox });
            return;
        }

        // Empty leaf node
        if self.is_leaf() && self.leaf_data.len() == 0 {
            self.leaf_data.push(OctreeData { index: index, bbox: object_bbox });
            return;
        }

        // Occupied leaf node and not max depth: subdivide node
        if self.is_leaf() && self.leaf_data.len() == 1 {
            self.subdivide();
            let old = self.leaf_data.remove(0);
            // Reinsert old node and then fall through to insert current object
            self.insert(old.index, old.bbox);
        }

        // Interior node (has children)
        for child in self.children.iter_mut() {
            if child.bbox.overlaps(&object_bbox) {
                child.insert(index, object_bbox);
            }
        }
    }

    fn is_leaf(&self) -> bool {
        self.children.len() == 0
    }
}

// TODO: sell: Prims can later implement a Bounded3D trait containing a method
//             that returns Option<BBox>.  Some if finite, None if infinite.
//             Then we can use impl<T: Bounded3D> Octree<Box<T>>, probably!

impl Octree<Box<Prim+Send+Sync>> {
    #[allow(dead_code)]
    pub fn new_from_prims(prims: Vec<Box<Prim+Send+Sync>>) -> Octree<Box<Prim+Send+Sync>> {
        let bounds = get_bounds_from_objects(&prims);
        let (finites, infinites): (Vec<Box<Prim+Send+Sync>>, Vec<Box<Prim+Send+Sync>>) = prims.into_iter().partition(|prim| prim.bounding().is_some());
        // pbrt recommended max depth for a k-d tree (though, we're using an octree)
        // For a k-d tree: 8 + 1.3 * log2(N)
        let depth = (1.2 * (finites.len() as f64).log(8.0)).round() as i32;

        println!("Octree maximum depth {}", depth);
        let mut root_node = OctreeNode::new(bounds, depth);
        for (i, prim) in finites.iter().enumerate() {
            root_node.insert(i, prim.bounding().unwrap());
        }

        Octree {
            prims: finites,
            infinites: infinites,
            root: root_node,
        }
    }

    pub fn get_intersected_objects<'a>(&'a self, ray: &'a Ray) -> OctreeIterator<'a, Box<Prim+Send+Sync>> {
        OctreeIterator::new(self, ray)
    }
}

struct OctreeIterator<'a, T:'a> {
    prims: &'a [T],
    stack: Vec<&'a OctreeNode<T>>,
    cur_iter: Option<Iter<'a, OctreeData>>,
    ray: &'a Ray,
    infinites: Iter<'a, T>,
    just_infinites: bool
}

impl<'a> OctreeIterator<'a, Box<Prim+Send+Sync>> {
    fn new<'b>(octree: &'b Octree<Box<Prim+Send+Sync>>, ray: &'b Ray) -> OctreeIterator<'b, Box<Prim+Send+Sync>> {
            OctreeIterator {
            prims: &octree.prims[],
            stack: vec![&octree.root],
            cur_iter: None,
            ray: ray,
            infinites: octree.infinites.iter(),
            just_infinites: false
        }
    }
}

impl<'a> Iterator for OctreeIterator<'a, Box<Prim+Send+Sync>> {
    type Item = &'a Box<Prim+Send+Sync>;

    fn next(&mut self) -> Option<&'a Box<Prim+Send+Sync>> {
        if self.just_infinites {
            return self.infinites.next();
        }
        loop {
            let (new_cur_iter, val) = match self.cur_iter.take() {
                Some(mut cur_iter) => match cur_iter.next() {
                    Some(val) => (Some(cur_iter), Some(val)),
                    None => (None, None)
                },
                None => match self.stack.pop() {
                    Some(node) => {
                        for child in node.children.iter() {
                            if child.bbox.intersects(self.ray) {
                                self.stack.push(child);
                            }
                        }
                        (Some(node.leaf_data.iter()), None)
                    },
                    None => break  // Empty stack and no iterator
                }
            };
            self.cur_iter = new_cur_iter;
            match val {
                Some(val) => {
                    if val.intersects(self.ray) {
                        return Some(&self.prims[val.index]);
                    }
                },
                None => (),
            }
        }
        self.just_infinites = true;
        self.infinites.next()
    }
}
<|endoftext|>


<commit_before>use ws;
use std; // NOTE: in submodules, lookup path is relative to this module, so we must `use std`
use time;
use uuid::Uuid;
use std::sync::{Arc,Mutex};
use std::collections::HashMap;

#[derive(Debug, Clone, Copy)]
pub struct Connection {
    uuid: Uuid,
}

impl std::fmt::Display for Connection {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "conn{{{}}}", self.uuid)
    }
}

type ConnectionMap = Arc<Mutex<HashMap<Uuid,Connection>>>;

struct WSServer {
    out: ws::Sender,
    connections: ConnectionMap,
}

impl ws::Handler for WSServer {
    fn on_request(&mut self, req: &ws::Request) -> ws::Result<ws::Response> {
        let mut resp = ws::Response::from_request(req).unwrap();

        let mut conn_map = self.connections.lock().unwrap();

        println!("ws:req[{}]", time::precise_time_ns());

        let new_uuid = Uuid::new_v4();
        let new_conn = Connection {
            uuid: new_uuid
        };
        conn_map.insert(new_conn.uuid, new_conn);
        println!("ws:req: new user with uuid {}", new_uuid);
        println!("{} connected users", conn_map.len());

        println!("ws:req: putting cookie: bzwf_anon_wstx={}; ", new_conn);
        let new_bzwf_cookie_str = format!("bzwf_anon_wstx={}; ", new_conn);
        {
            let headers = resp.headers_mut();
            headers.push((
                String::from("Set-Cookie"),
                new_bzwf_cookie_str.as_bytes().to_vec()
            ));
        }

        Ok(resp)
    }

    fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
        // TODO
        println!("ws:rcv[{}]: user with uuid {} sent ws msg {}",
                 time::precise_time_ns(),
                 "[[[ we don't have uuids in ws yet ]]]",
                 msg);
        self.out.send("I hear you loud and clear").unwrap();
        Ok(())
    }

    fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
        // TODO
        println!("ws:opn[{}]: user with uuid {} opened ws cxn",
                 time::precise_time_ns(),
                 "[[[ we don't have uuids in ws yet ]]]");
        Ok(())
    }

    fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
        println!("ws:cls[{}]: user with uuid {} closed ws cxn\n\tCode [{:?}] reason: {}",
                 time::precise_time_ns(),
                 "[[[ we don't have uuids in ws yet ]]]",
                 code,
                 reason);
        // TODO
    }

    fn on_error(&mut self, err: ws::Error) {
        println!("ws:err[{}]: user with uuid {} got error {}",
                 time::precise_time_ns(),
                 "[[[ we don't have uuids in ws yet ]]]",
                 err);
        // TODO
    }
}

pub fn server (domain: String) -> () {
    let connections : ConnectionMap = Arc::new(Mutex::new(HashMap::new()));
    let addr = format!("{}:3001", domain);
    println!("WebSockets server listening on {}", addr);
    ws::listen(addr, |out| WSServer {
        out: out,
        connections: connections.clone(),
    }).unwrap();
}
<commit_msg>Feature: cruddy cookie parser<commit_after>use ws;
use std; // NOTE: in submodules, lookup path is relative to this module, so we must `use std`
use time;
use uuid::Uuid;
use std::sync::{Arc,Mutex};
use std::collections::HashMap;

#[derive(Debug, Clone, Copy)]
pub struct Connection {
    uuid: Uuid,
}

impl std::fmt::Display for Connection {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "conn{{{}}}", self.uuid)
    }
}

type ConnectionMap = Arc<Mutex<HashMap<Uuid,Connection>>>;

struct WSServer {
    out: ws::Sender,
    connections: ConnectionMap,
}

impl ws::Handler for WSServer {
    fn on_request(&mut self, req: &ws::Request) -> ws::Result<ws::Response> {
        let mut resp = ws::Response::from_request(req).unwrap();

        let mut conn_map = self.connections.lock().unwrap();

        println!("ws:req[{}]", time::precise_time_ns());

        if let Some(cookies_bytes) = req.header("cookie") {
            println!("cookies?");
            if let Ok(cookies) = String::from_utf8(cookies_bytes.to_vec()) {
                println!("coooookies");
                // NOTE(jordan): reverse in order to sort by recency
                for cookie_pair_str in cookies.rsplit(";") {
                    let mut cookie_pair = cookie_pair_str.split("=");
                    match (cookie_pair.next(), cookie_pair.next()) {
                        (Some(cookie_name), Some(cookie_value)) => {
                            println!("cookie {} says {}", cookie_name, cookie_value);
                        },
                        (None, _) => println!("bad cookie?"),
                        (_, None) => println!("bad cookie?")
                    }
                }
            };
        };

        let new_uuid = Uuid::new_v4();
        let new_conn = Connection {
            uuid: new_uuid
        };
        conn_map.insert(new_conn.uuid, new_conn);
        println!("ws:req: new user with uuid {}", new_uuid);
        println!("{} connected users", conn_map.len());

        println!("ws:req: putting cookie: bzwf_anon_wstx={}; ", new_conn);
        let new_bzwf_cookie_str = format!("bzwf_anon_wstx={}; ", new_conn);
        {
            let headers = resp.headers_mut();
            headers.push((
                String::from("Set-Cookie"),
                new_bzwf_cookie_str.as_bytes().to_vec()
            ));
        }

        Ok(resp)
    }

    fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
        // TODO
        println!("ws:rcv[{}]: user with uuid {} sent ws msg {}",
                 time::precise_time_ns(),
                 "[[[ we don't have uuids in ws yet ]]]",
                 msg);
        self.out.send("I hear you loud and clear").unwrap();
        Ok(())
    }

    fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
        // TODO
        println!("ws:opn[{}]: user with uuid {} opened ws cxn",
                 time::precise_time_ns(),
                 "[[[ we don't have uuids in ws yet ]]]");
        Ok(())
    }

    fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
        println!("ws:cls[{}]: user with uuid {} closed ws cxn\n\tCode [{:?}] reason: {}",
                 time::precise_time_ns(),
                 "[[[ we don't have uuids in ws yet ]]]",
                 code,
                 reason);
        // TODO
    }

    fn on_error(&mut self, err: ws::Error) {
        println!("ws:err[{}]: user with uuid {} got error {}",
                 time::precise_time_ns(),
                 "[[[ we don't have uuids in ws yet ]]]",
                 err);
        // TODO
    }
}

pub fn server (domain: String) -> () {
    let connections : ConnectionMap = Arc::new(Mutex::new(HashMap::new()));
    let addr = format!("{}:3001", domain);
    println!("WebSockets server listening on {}", addr);
    ws::listen(addr, |out| WSServer {
        out: out,
        connections: connections.clone(),
    }).unwrap();
}
<|endoftext|>


<commit_before>//! `hermit-abi` is small interface to call functions from the unikernel
//! [RustyHermit](https://github.com/hermitcore/libhermit-rs).

#![cfg_attr(feature = "rustc-dep-of-std", no_std)]
#![feature(const_raw_ptr_to_usize_cast)]
extern crate libc;

pub mod tcpstream;

use libc::c_void;

// sysmbols, which are part of the library operating system
extern "C" {
	fn sys_get_processor_count() -> usize;
	fn sys_malloc(size: usize, align: usize) -> *mut u8;
	fn sys_realloc(ptr: *mut u8, size: usize, align: usize, new_size: usize) -> *mut u8;
	fn sys_free(ptr: *mut u8, size: usize, align: usize);
	fn sys_notify(id: usize, count: i32) -> i32;
	fn sys_add_queue(id: usize, timeout_ns: i64) -> i32;
	fn sys_wait(id: usize) -> i32;
	fn sys_destroy_queue(id: usize) -> i32;
	fn sys_read(fd: i32, buf: *mut u8, len: usize) -> isize;
	fn sys_write(fd: i32, buf: *const u8, len: usize) -> isize;
	fn sys_close(fd: i32) -> i32;
	fn sys_sem_init(sem: *mut *const c_void, value: u32) -> i32;
	fn sys_sem_destroy(sem: *const c_void) -> i32;
	fn sys_sem_post(sem: *const c_void) -> i32;
	fn sys_sem_trywait(sem: *const c_void) -> i32;
	fn sys_sem_timedwait(sem: *const c_void, ms: u32) -> i32;
	fn sys_recmutex_init(recmutex: *mut *const c_void) -> i32;
	fn sys_recmutex_destroy(recmutex: *const c_void) -> i32;
	fn sys_recmutex_lock(recmutex: *const c_void) -> i32;
	fn sys_recmutex_unlock(recmutex: *const c_void) -> i32;
	fn sys_getpid() -> u32;
	fn sys_exit(arg: i32) -> !;
	fn sys_abort() -> !;
	fn sys_usleep(usecs: u64);
	fn sys_spawn(
		id: *mut Tid,
		func: extern "C" fn(usize),
		arg: usize,
		prio: u8,
		core_id: isize,
	) -> i32;
	fn sys_join(id: Tid) -> i32;
	fn sys_yield();
	fn sys_clock_gettime(clock_id: u64, tp: *mut timespec) -> i32;
	fn sys_open(name: *const i8, flags: i32, mode: i32) -> i32;
	fn sys_unlink(name: *const i8) -> i32;
	fn sys_network_init() -> i32;
}

/// A thread handle type
pub type Tid = u32;

/// A handle, identifying a socket
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
pub struct Handle(usize);

pub const NSEC_PER_SEC: u64 = 1_000_000_000;
pub const CLOCK_REALTIME: u64 = 1;
pub const CLOCK_MONOTONIC: u64 = 4;
pub const STDIN_FILENO: libc::c_int = 0;
pub const STDOUT_FILENO: libc::c_int = 1;
pub const STDERR_FILENO: libc::c_int = 2;
pub const HIGH_PRIO: u8 = 3;
pub const NORMAL_PRIO: u8 = 2;
pub const LOW_PRIO: u8 = 1;
pub const O_RDONLY: i32 = 0o0;
pub const O_WRONLY: i32 = 0o1;
pub const O_RDWR: i32 = 0o2;
pub const O_CREAT: i32 = 0o100;
pub const O_EXCL: i32 = 0o200;
pub const O_TRUNC: i32 = 0o1000;
pub const O_APPEND: i32 = 0o2000;

/// returns true if file descriptor `fd` is a tty
pub fn isatty(_fd: libc::c_int) -> bool {
	false
}

/// intialize the network stack
pub fn network_init() -> i32 {
	unsafe { sys_network_init() }
}

/// `timespec` is used by `clock_gettime` to retrieve the
/// current time
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct timespec {
	/// seconds
	pub tv_sec: i64,
	/// nanoseconds
	pub tv_nsec: i64,
}

/// determines the number of activated processors
#[inline(always)]
pub unsafe fn get_processor_count() -> usize {
	sys_get_processor_count()
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn malloc(size: usize, align: usize) -> *mut u8 {
	sys_malloc(size, align)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn realloc(ptr: *mut u8, size: usize, align: usize, new_size: usize) -> *mut u8 {
	sys_realloc(ptr, size, align, new_size)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn free(ptr: *mut u8, size: usize, align: usize) {
	sys_free(ptr, size, align)
}

#[inline(always)]
pub unsafe fn notify(id: usize, count: i32) -> i32 {
	sys_notify(id, count)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn add_queue(id: usize, timeout_ns: i64) -> i32 {
	sys_add_queue(id, timeout_ns)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn wait(id: usize) -> i32 {
	sys_wait(id)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn destroy_queue(id: usize) -> i32 {
	sys_destroy_queue(id)
}

/// read from a file descriptor
///
/// read() attempts to read `len` bytes of data from the object
/// referenced by the descriptor `fd` into the buffer pointed
/// to by `buf`.
#[inline(always)]
pub unsafe fn read(fd: i32, buf: *mut u8, len: usize) -> isize {
	sys_read(fd, buf, len)
}

/// write to a file descriptor
///
/// write() attempts to write `len` of data to the object
/// referenced by the descriptor `fd` from the
/// buffer pointed to by `buf`.
#[inline(always)]
pub unsafe fn write(fd: i32, buf: *const u8, len: usize) -> isize {
	sys_write(fd, buf, len)
}

/// close a file descriptor
///
/// The close() call deletes a file descriptor `fd` from the object
/// reference table.
#[inline(always)]
pub unsafe fn close(fd: i32) -> i32 {
	sys_close(fd)
}

/// sem_init() initializes the unnamed semaphore at the address
/// pointed to by `sem`.  The `value` argument specifies the
/// initial value for the semaphore.
#[inline(always)]
pub unsafe fn sem_init(sem: *mut *const c_void, value: u32) -> i32 {
	sys_sem_init(sem, value)
}

/// sem_destroy() frees the unnamed semaphore at the address
/// pointed to by `sem`.
#[inline(always)]
pub unsafe fn sem_destroy(sem: *const c_void) -> i32 {
	sys_sem_destroy(sem)
}

/// sem_post() increments the semaphore pointed to by `sem`.
/// If the semaphore's value consequently becomes greater
/// than zero, then another thread blocked in a sem_wait call
/// will be woken up and proceed to lock the semaphore.
#[inline(always)]
pub unsafe fn sem_post(sem: *const c_void) -> i32 {
	sys_sem_post(sem)
}

/// try to decrement a semaphore
///
/// sem_trywait() is the same as sem_timedwait(), except that
/// if the  decrement cannot be immediately performed, then  call
/// returns a negative value instead of blocking.
#[inline(always)]
pub unsafe fn sem_trywait(sem: *const c_void) -> i32 {
	sys_sem_trywait(sem)
}

/// decrement a semaphore
///
/// sem_timedwait() decrements the semaphore pointed to by `sem`.
/// If the semaphore's value is greater than zero, then the
/// the function returns immediately. If the semaphore currently
/// has the value zero, then the call blocks until either
/// it becomes possible to perform the decrement of the time limit
/// to wait for the semaphore is expired. A time limit `ms` of
/// means infinity waiting time.
#[inline(always)]
pub unsafe fn sem_timedwait(sem: *const c_void, ms: u32) -> i32 {
	sys_sem_timedwait(sem, ms)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn recmutex_init(recmutex: *mut *const c_void) -> i32 {
	sys_recmutex_init(recmutex)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn recmutex_destroy(recmutex: *const c_void) -> i32 {
	sys_recmutex_destroy(recmutex)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn recmutex_lock(recmutex: *const c_void) -> i32 {
	sys_recmutex_lock(recmutex)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn recmutex_unlock(recmutex: *const c_void) -> i32 {
	sys_recmutex_unlock(recmutex)
}

/// Determines the id of the current thread
#[inline(always)]
pub unsafe fn getpid() -> u32 {
	sys_getpid()
}

/// cause normal termination and return `arg`
/// to the host system
#[inline(always)]
pub unsafe fn exit(arg: i32) -> ! {
	sys_exit(arg)
}

/// cause abnormal termination
#[inline(always)]
pub unsafe fn abort() -> ! {
	sys_abort()
}

/// suspend execution for microsecond intervals
///
/// The usleep() function suspends execution of the calling
/// thread for (at least) `usecs` microseconds.
#[inline(always)]
pub unsafe fn usleep(usecs: u64) {
	sys_usleep(usecs)
}

/// spawn a new thread
///
/// spawn() starts a new thread. The new thread starts execution
/// by invoking `func(usize)`; `arg` is passed as the argument
/// to `func`. `prio` defines the priority of the new thread,
/// which can be between `LOW_PRIO` and `HIGH_PRIO`.
/// `core_id` defines the core, where the thread is located.
/// A negative value give the operating system the possibility
/// to select the core by its own.
#[inline(always)]
pub unsafe fn spawn(
	id: *mut Tid,
	func: extern "C" fn(usize),
	arg: usize,
	prio: u8,
	core_id: isize,
) -> i32 {
	sys_spawn(id, func, arg, prio, core_id)
}

/// join with a terminated thread
///
/// The join() function waits for the thread specified by `id`
/// to terminate.
#[inline(always)]
pub unsafe fn join(id: Tid) -> i32 {
	sys_join(id)
}

/// yield the processor
///
/// causes the calling thread to relinquish the CPU. The thread
/// is moved to the end of the queue for its static priority.
#[inline(always)]
pub unsafe fn yield_now() {
	sys_yield()
}

/// get current time
///
/// The clock_gettime() functions allow the calling thread
/// to retrieve the value used by a clock which is specified
/// by `clock_id`.
///
/// `CLOCK_REALTIME`: the system's real time clock,
/// expressed as the amount of time since the Epoch.
///
/// `CLOCK_MONOTONIC`: clock that increments monotonically,
/// tracking the time since an arbitrary point
#[inline(always)]
pub unsafe fn clock_gettime(clock_id: u64, tp: *mut timespec) -> i32 {
	sys_clock_gettime(clock_id, tp)
}

/// open and possibly create a file
///
/// The open() system call opens the file specified by `name`.
/// If the specified file does not exist, it may optionally
/// be created by open().
#[inline(always)]
pub unsafe fn open(name: *const i8, flags: i32, mode: i32) -> i32 {
	sys_open(name, flags, mode)
}

/// delete the file it refers to `name`
#[inline(always)]
pub unsafe fn unlink(name: *const i8) -> i32 {
	sys_unlink(name)
}
<commit_msg>use the same struct to handle priorities like libhermit<commit_after>//! `hermit-abi` is small interface to call functions from the unikernel
//! [RustyHermit](https://github.com/hermitcore/libhermit-rs).

#![cfg_attr(feature = "rustc-dep-of-std", no_std)]
#![feature(const_raw_ptr_to_usize_cast)]
extern crate libc;

pub mod tcpstream;

use libc::c_void;

// sysmbols, which are part of the library operating system
extern "C" {
	fn sys_get_processor_count() -> usize;
	fn sys_malloc(size: usize, align: usize) -> *mut u8;
	fn sys_realloc(ptr: *mut u8, size: usize, align: usize, new_size: usize) -> *mut u8;
	fn sys_free(ptr: *mut u8, size: usize, align: usize);
	fn sys_notify(id: usize, count: i32) -> i32;
	fn sys_add_queue(id: usize, timeout_ns: i64) -> i32;
	fn sys_wait(id: usize) -> i32;
	fn sys_destroy_queue(id: usize) -> i32;
	fn sys_read(fd: i32, buf: *mut u8, len: usize) -> isize;
	fn sys_write(fd: i32, buf: *const u8, len: usize) -> isize;
	fn sys_close(fd: i32) -> i32;
	fn sys_sem_init(sem: *mut *const c_void, value: u32) -> i32;
	fn sys_sem_destroy(sem: *const c_void) -> i32;
	fn sys_sem_post(sem: *const c_void) -> i32;
	fn sys_sem_trywait(sem: *const c_void) -> i32;
	fn sys_sem_timedwait(sem: *const c_void, ms: u32) -> i32;
	fn sys_recmutex_init(recmutex: *mut *const c_void) -> i32;
	fn sys_recmutex_destroy(recmutex: *const c_void) -> i32;
	fn sys_recmutex_lock(recmutex: *const c_void) -> i32;
	fn sys_recmutex_unlock(recmutex: *const c_void) -> i32;
	fn sys_getpid() -> u32;
	fn sys_exit(arg: i32) -> !;
	fn sys_abort() -> !;
	fn sys_usleep(usecs: u64);
	fn sys_spawn(
		id: *mut Tid,
		func: extern "C" fn(usize),
		arg: usize,
		prio: u8,
		core_id: isize,
	) -> i32;
	fn sys_join(id: Tid) -> i32;
	fn sys_yield();
	fn sys_clock_gettime(clock_id: u64, tp: *mut timespec) -> i32;
	fn sys_open(name: *const i8, flags: i32, mode: i32) -> i32;
	fn sys_unlink(name: *const i8) -> i32;
	fn sys_network_init() -> i32;
}

/// A thread handle type
pub type Tid = u32;

/// Priority of a thread
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
pub struct Priority(u8);

impl Priority {
    pub const fn into(self) -> u8 {
        self.0
    }

    pub const fn from(x: u8) -> Self {
        Priority(x)
    }
}

pub const HIGH_PRIO: Priority = Priority::from(3);
pub const NORMAL_PRIO: Priority = Priority::from(2);
pub const LOW_PRIO: Priority = Priority::from(1);

/// A handle, identifying a socket
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
pub struct Handle(usize);

pub const NSEC_PER_SEC: u64 = 1_000_000_000;
pub const CLOCK_REALTIME: u64 = 1;
pub const CLOCK_MONOTONIC: u64 = 4;
pub const STDIN_FILENO: libc::c_int = 0;
pub const STDOUT_FILENO: libc::c_int = 1;
pub const STDERR_FILENO: libc::c_int = 2;
pub const O_RDONLY: i32 = 0o0;
pub const O_WRONLY: i32 = 0o1;
pub const O_RDWR: i32 = 0o2;
pub const O_CREAT: i32 = 0o100;
pub const O_EXCL: i32 = 0o200;
pub const O_TRUNC: i32 = 0o1000;
pub const O_APPEND: i32 = 0o2000;

/// returns true if file descriptor `fd` is a tty
pub fn isatty(_fd: libc::c_int) -> bool {
	false
}

/// intialize the network stack
pub fn network_init() -> i32 {
	unsafe { sys_network_init() }
}

/// `timespec` is used by `clock_gettime` to retrieve the
/// current time
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct timespec {
	/// seconds
	pub tv_sec: i64,
	/// nanoseconds
	pub tv_nsec: i64,
}

/// determines the number of activated processors
#[inline(always)]
pub unsafe fn get_processor_count() -> usize {
	sys_get_processor_count()
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn malloc(size: usize, align: usize) -> *mut u8 {
	sys_malloc(size, align)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn realloc(ptr: *mut u8, size: usize, align: usize, new_size: usize) -> *mut u8 {
	sys_realloc(ptr, size, align, new_size)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn free(ptr: *mut u8, size: usize, align: usize) {
	sys_free(ptr, size, align)
}

#[inline(always)]
pub unsafe fn notify(id: usize, count: i32) -> i32 {
	sys_notify(id, count)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn add_queue(id: usize, timeout_ns: i64) -> i32 {
	sys_add_queue(id, timeout_ns)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn wait(id: usize) -> i32 {
	sys_wait(id)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn destroy_queue(id: usize) -> i32 {
	sys_destroy_queue(id)
}

/// read from a file descriptor
///
/// read() attempts to read `len` bytes of data from the object
/// referenced by the descriptor `fd` into the buffer pointed
/// to by `buf`.
#[inline(always)]
pub unsafe fn read(fd: i32, buf: *mut u8, len: usize) -> isize {
	sys_read(fd, buf, len)
}

/// write to a file descriptor
///
/// write() attempts to write `len` of data to the object
/// referenced by the descriptor `fd` from the
/// buffer pointed to by `buf`.
#[inline(always)]
pub unsafe fn write(fd: i32, buf: *const u8, len: usize) -> isize {
	sys_write(fd, buf, len)
}

/// close a file descriptor
///
/// The close() call deletes a file descriptor `fd` from the object
/// reference table.
#[inline(always)]
pub unsafe fn close(fd: i32) -> i32 {
	sys_close(fd)
}

/// sem_init() initializes the unnamed semaphore at the address
/// pointed to by `sem`.  The `value` argument specifies the
/// initial value for the semaphore.
#[inline(always)]
pub unsafe fn sem_init(sem: *mut *const c_void, value: u32) -> i32 {
	sys_sem_init(sem, value)
}

/// sem_destroy() frees the unnamed semaphore at the address
/// pointed to by `sem`.
#[inline(always)]
pub unsafe fn sem_destroy(sem: *const c_void) -> i32 {
	sys_sem_destroy(sem)
}

/// sem_post() increments the semaphore pointed to by `sem`.
/// If the semaphore's value consequently becomes greater
/// than zero, then another thread blocked in a sem_wait call
/// will be woken up and proceed to lock the semaphore.
#[inline(always)]
pub unsafe fn sem_post(sem: *const c_void) -> i32 {
	sys_sem_post(sem)
}

/// try to decrement a semaphore
///
/// sem_trywait() is the same as sem_timedwait(), except that
/// if the  decrement cannot be immediately performed, then  call
/// returns a negative value instead of blocking.
#[inline(always)]
pub unsafe fn sem_trywait(sem: *const c_void) -> i32 {
	sys_sem_trywait(sem)
}

/// decrement a semaphore
///
/// sem_timedwait() decrements the semaphore pointed to by `sem`.
/// If the semaphore's value is greater than zero, then the
/// the function returns immediately. If the semaphore currently
/// has the value zero, then the call blocks until either
/// it becomes possible to perform the decrement of the time limit
/// to wait for the semaphore is expired. A time limit `ms` of
/// means infinity waiting time.
#[inline(always)]
pub unsafe fn sem_timedwait(sem: *const c_void, ms: u32) -> i32 {
	sys_sem_timedwait(sem, ms)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn recmutex_init(recmutex: *mut *const c_void) -> i32 {
	sys_recmutex_init(recmutex)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn recmutex_destroy(recmutex: *const c_void) -> i32 {
	sys_recmutex_destroy(recmutex)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn recmutex_lock(recmutex: *const c_void) -> i32 {
	sys_recmutex_lock(recmutex)
}

#[doc(hidden)]
#[inline(always)]
pub unsafe fn recmutex_unlock(recmutex: *const c_void) -> i32 {
	sys_recmutex_unlock(recmutex)
}

/// Determines the id of the current thread
#[inline(always)]
pub unsafe fn getpid() -> u32 {
	sys_getpid()
}

/// cause normal termination and return `arg`
/// to the host system
#[inline(always)]
pub unsafe fn exit(arg: i32) -> ! {
	sys_exit(arg)
}

/// cause abnormal termination
#[inline(always)]
pub unsafe fn abort() -> ! {
	sys_abort()
}

/// suspend execution for microsecond intervals
///
/// The usleep() function suspends execution of the calling
/// thread for (at least) `usecs` microseconds.
#[inline(always)]
pub unsafe fn usleep(usecs: u64) {
	sys_usleep(usecs)
}

/// spawn a new thread
///
/// spawn() starts a new thread. The new thread starts execution
/// by invoking `func(usize)`; `arg` is passed as the argument
/// to `func`. `prio` defines the priority of the new thread,
/// which can be between `LOW_PRIO` and `HIGH_PRIO`.
/// `core_id` defines the core, where the thread is located.
/// A negative value give the operating system the possibility
/// to select the core by its own.
#[inline(always)]
pub unsafe fn spawn(
	id: *mut Tid,
	func: extern "C" fn(usize),
	arg: usize,
	prio: u8,
	core_id: isize,
) -> i32 {
	sys_spawn(id, func, arg, prio, core_id)
}

/// join with a terminated thread
///
/// The join() function waits for the thread specified by `id`
/// to terminate.
#[inline(always)]
pub unsafe fn join(id: Tid) -> i32 {
	sys_join(id)
}

/// yield the processor
///
/// causes the calling thread to relinquish the CPU. The thread
/// is moved to the end of the queue for its static priority.
#[inline(always)]
pub unsafe fn yield_now() {
	sys_yield()
}

/// get current time
///
/// The clock_gettime() functions allow the calling thread
/// to retrieve the value used by a clock which is specified
/// by `clock_id`.
///
/// `CLOCK_REALTIME`: the system's real time clock,
/// expressed as the amount of time since the Epoch.
///
/// `CLOCK_MONOTONIC`: clock that increments monotonically,
/// tracking the time since an arbitrary point
#[inline(always)]
pub unsafe fn clock_gettime(clock_id: u64, tp: *mut timespec) -> i32 {
	sys_clock_gettime(clock_id, tp)
}

/// open and possibly create a file
///
/// The open() system call opens the file specified by `name`.
/// If the specified file does not exist, it may optionally
/// be created by open().
#[inline(always)]
pub unsafe fn open(name: *const i8, flags: i32, mode: i32) -> i32 {
	sys_open(name, flags, mode)
}

/// delete the file it refers to `name`
#[inline(always)]
pub unsafe fn unlink(name: *const i8) -> i32 {
	sys_unlink(name)
}
<|endoftext|>


<commit_before>// mod disk_db;
mod block_at_slot;
mod errors;
mod impls;
mod leveldb_store;
mod memory_db;

pub use self::leveldb_store::LevelDB;
pub use self::memory_db::MemoryDB;
pub use errors::Error;
pub use types::*;
pub type DBValue = Vec<u8>;

pub trait Store: Sync + Send + Sized {
    fn put(&self, key: &Hash256, item: &impl StoreItem) -> Result<(), Error> {
        item.db_put(self, key)
    }

    fn get<I: StoreItem>(&self, key: &Hash256) -> Result<Option<I>, Error> {
        I::db_get(self, key)
    }

    fn exists<I: StoreItem>(&self, key: &Hash256) -> Result<bool, Error> {
        I::db_exists(self, key)
    }

    fn delete<I: StoreItem>(&self, key: &Hash256) -> Result<(), Error> {
        I::db_delete(self, key)
    }

    fn get_block_at_preceeding_slot(
        &self,
        start_block_root: Hash256,
        slot: Slot,
    ) -> Result<Option<(Hash256, BeaconBlock)>, Error> {
        block_at_slot::get_block_at_preceeding_slot(self, slot, start_block_root)
    }

    fn get_bytes(&self, col: &str, key: &[u8]) -> Result<Option<DBValue>, Error>;

    fn put_bytes(&self, col: &str, key: &[u8], val: &[u8]) -> Result<(), Error>;

    fn key_exists(&self, col: &str, key: &[u8]) -> Result<bool, Error>;

    fn key_delete(&self, col: &str, key: &[u8]) -> Result<(), Error>;
}

pub enum DBColumn {
    BeaconBlock,
    BeaconState,
    BeaconChain,
}

impl<'a> Into<&'a str> for DBColumn {
    /// Returns a `&str` that can be used for keying a key-value data base.
    fn into(self) -> &'a str {
        match self {
            DBColumn::BeaconBlock => &"blk",
            DBColumn::BeaconState => &"ste",
            DBColumn::BeaconChain => &"bch",
        }
    }
}

pub trait StoreItem: Sized {
    fn db_column() -> DBColumn;

    fn as_store_bytes(&self) -> Vec<u8>;

    fn from_store_bytes(bytes: &mut [u8]) -> Result<Self, Error>;

    fn db_put(&self, store: &impl Store, key: &Hash256) -> Result<(), Error> {
        let column = Self::db_column().into();
        let key = key.as_bytes();

        store
            .put_bytes(column, key, &self.as_store_bytes())
            .map_err(|e| e.into())
    }

    fn db_get(store: &impl Store, key: &Hash256) -> Result<Option<Self>, Error> {
        let column = Self::db_column().into();
        let key = key.as_bytes();

        match store.get_bytes(column, key)? {
            Some(mut bytes) => Ok(Some(Self::from_store_bytes(&mut bytes[..])?)),
            None => Ok(None),
        }
    }

    fn db_exists(store: &impl Store, key: &Hash256) -> Result<bool, Error> {
        let column = Self::db_column().into();
        let key = key.as_bytes();

        store.key_exists(column, key)
    }

    fn db_delete(store: &impl Store, key: &Hash256) -> Result<(), Error> {
        let column = Self::db_column().into();
        let key = key.as_bytes();

        store.key_delete(column, key)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ssz::{Decode, Encode};
    use ssz_derive::{Decode, Encode};
    use tempfile::tempdir;

    #[derive(PartialEq, Debug, Encode, Decode)]
    struct StorableThing {
        a: u64,
        b: u64,
    }

    impl StoreItem for StorableThing {
        fn db_column() -> DBColumn {
            DBColumn::BeaconBlock
        }

        fn as_store_bytes(&self) -> Vec<u8> {
            self.as_ssz_bytes()
        }

        fn from_store_bytes(bytes: &mut [u8]) -> Result<Self, Error> {
            Self::from_ssz_bytes(bytes).map_err(Into::into)
        }
    }

    #[test]
    fn leveldb_can_store_and_retrieve() {
        let dir = tempdir().unwrap();
        let path = dir.path();

        let store = LevelDB::open(&path).unwrap();

        let key = Hash256::random();
        let item = StorableThing { a: 1, b: 42 };

        store.put(&key, &item).unwrap();

        let retrieved = store.get(&key).unwrap().unwrap();

        assert_eq!(item, retrieved);
    }

    #[test]
    fn memorydb_can_store_and_retrieve() {
        let store = MemoryDB::open();

        let key = Hash256::random();
        let item = StorableThing { a: 1, b: 42 };

        store.put(&key, &item).unwrap();

        let retrieved = store.get(&key).unwrap().unwrap();

        assert_eq!(item, retrieved);
    }

    #[test]
    fn exists() {
        let store = MemoryDB::open();
        let key = Hash256::random();
        let item = StorableThing { a: 1, b: 42 };

        assert_eq!(store.exists::<StorableThing>(&key).unwrap(), false);

        store.put(&key, &item).unwrap();

        assert_eq!(store.exists::<StorableThing>(&key).unwrap(), true);

        store.delete::<StorableThing>(&key).unwrap();

        assert_eq!(store.exists::<StorableThing>(&key).unwrap(), false);
    }
}
<commit_msg>Improve testing for `Store` impls<commit_after>// mod disk_db;
mod block_at_slot;
mod errors;
mod impls;
mod leveldb_store;
mod memory_db;

pub use self::leveldb_store::LevelDB;
pub use self::memory_db::MemoryDB;
pub use errors::Error;
pub use types::*;
pub type DBValue = Vec<u8>;

pub trait Store: Sync + Send + Sized {
    fn put(&self, key: &Hash256, item: &impl StoreItem) -> Result<(), Error> {
        item.db_put(self, key)
    }

    fn get<I: StoreItem>(&self, key: &Hash256) -> Result<Option<I>, Error> {
        I::db_get(self, key)
    }

    fn exists<I: StoreItem>(&self, key: &Hash256) -> Result<bool, Error> {
        I::db_exists(self, key)
    }

    fn delete<I: StoreItem>(&self, key: &Hash256) -> Result<(), Error> {
        I::db_delete(self, key)
    }

    fn get_block_at_preceeding_slot(
        &self,
        start_block_root: Hash256,
        slot: Slot,
    ) -> Result<Option<(Hash256, BeaconBlock)>, Error> {
        block_at_slot::get_block_at_preceeding_slot(self, slot, start_block_root)
    }

    fn get_bytes(&self, col: &str, key: &[u8]) -> Result<Option<DBValue>, Error>;

    fn put_bytes(&self, col: &str, key: &[u8], val: &[u8]) -> Result<(), Error>;

    fn key_exists(&self, col: &str, key: &[u8]) -> Result<bool, Error>;

    fn key_delete(&self, col: &str, key: &[u8]) -> Result<(), Error>;
}

pub enum DBColumn {
    BeaconBlock,
    BeaconState,
    BeaconChain,
}

impl<'a> Into<&'a str> for DBColumn {
    /// Returns a `&str` that can be used for keying a key-value data base.
    fn into(self) -> &'a str {
        match self {
            DBColumn::BeaconBlock => &"blk",
            DBColumn::BeaconState => &"ste",
            DBColumn::BeaconChain => &"bch",
        }
    }
}

pub trait StoreItem: Sized {
    fn db_column() -> DBColumn;

    fn as_store_bytes(&self) -> Vec<u8>;

    fn from_store_bytes(bytes: &mut [u8]) -> Result<Self, Error>;

    fn db_put(&self, store: &impl Store, key: &Hash256) -> Result<(), Error> {
        let column = Self::db_column().into();
        let key = key.as_bytes();

        store
            .put_bytes(column, key, &self.as_store_bytes())
            .map_err(|e| e.into())
    }

    fn db_get(store: &impl Store, key: &Hash256) -> Result<Option<Self>, Error> {
        let column = Self::db_column().into();
        let key = key.as_bytes();

        match store.get_bytes(column, key)? {
            Some(mut bytes) => Ok(Some(Self::from_store_bytes(&mut bytes[..])?)),
            None => Ok(None),
        }
    }

    fn db_exists(store: &impl Store, key: &Hash256) -> Result<bool, Error> {
        let column = Self::db_column().into();
        let key = key.as_bytes();

        store.key_exists(column, key)
    }

    fn db_delete(store: &impl Store, key: &Hash256) -> Result<(), Error> {
        let column = Self::db_column().into();
        let key = key.as_bytes();

        store.key_delete(column, key)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ssz::{Decode, Encode};
    use ssz_derive::{Decode, Encode};
    use tempfile::tempdir;

    #[derive(PartialEq, Debug, Encode, Decode)]
    struct StorableThing {
        a: u64,
        b: u64,
    }

    impl StoreItem for StorableThing {
        fn db_column() -> DBColumn {
            DBColumn::BeaconBlock
        }

        fn as_store_bytes(&self) -> Vec<u8> {
            self.as_ssz_bytes()
        }

        fn from_store_bytes(bytes: &mut [u8]) -> Result<Self, Error> {
            Self::from_ssz_bytes(bytes).map_err(Into::into)
        }
    }

    fn test_impl(store: impl Store) {
        let key = Hash256::random();
        let item = StorableThing { a: 1, b: 42 };

        assert_eq!(store.exists::<StorableThing>(&key), Ok(false));

        store.put(&key, &item).unwrap();

        assert_eq!(store.exists::<StorableThing>(&key), Ok(true));

        let retrieved = store.get(&key).unwrap().unwrap();
        assert_eq!(item, retrieved);

        store.delete::<StorableThing>(&key).unwrap();

        assert_eq!(store.exists::<StorableThing>(&key), Ok(false));

        assert_eq!(store.get::<StorableThing>(&key), Ok(None));
    }

    #[test]
    fn leveldb() {
        let dir = tempdir().unwrap();
        let path = dir.path();
        let store = LevelDB::open(&path).unwrap();

        test_impl(store);
    }

    #[test]
    fn memorydb() {
        let store = MemoryDB::open();

        test_impl(store);
    }

    #[test]
    fn exists() {
        let store = MemoryDB::open();
        let key = Hash256::random();
        let item = StorableThing { a: 1, b: 42 };

        assert_eq!(store.exists::<StorableThing>(&key).unwrap(), false);

        store.put(&key, &item).unwrap();

        assert_eq!(store.exists::<StorableThing>(&key).unwrap(), true);

        store.delete::<StorableThing>(&key).unwrap();

        assert_eq!(store.exists::<StorableThing>(&key).unwrap(), false);
    }
}
<|endoftext|>


<commit_before><commit_msg>rename subcommand: 'refresh' => 'scan'<commit_after><|endoftext|>


<commit_before>use std::fs::File;
use std::io::{BufRead, BufReader};
mod node;
use node::*;

type Pyramid = Vec<Vec<usize>>;

fn main() {
    // let pyramid = get_pyramid("pyramid.txt");
    let pyramid = get_pyramid("mini.txt");
    let mut root = Node { val: pyramid[0][0], l: None, r: None };

    // populate treeee

    populate_binary_tree(&mut root, 1, 0, 1, &pyramid, pyramid.len());

    print_node(root, 0);
    root.print();
    // println!("{:?}", root);
}

fn populate_binary_tree(root: &mut Node, depth: usize, lidx: usize, ridx: usize, pyramid: &Pyramid, max_depth: usize) {

    if depth == max_depth {
        return
    }

    let mut l = Node { val: pyramid[depth][lidx], l: None, r: None };
    let mut r = Node { val: pyramid[depth][ridx], l: None, r: None };

    populate_binary_tree(&mut l, depth+1, lidx, ridx, pyramid, max_depth);
    populate_binary_tree(&mut r, depth+1, ridx, ridx + 1, pyramid, max_depth);

    root.l = Some(Box::new(l));
    root.r = Some(Box::new(r));
}

fn print_node( root: Node, depth: usize ) {

    match root.r {
        Some(node) => {
            print_node(*node, depth + 1);
        }
        None => return,
    }

    println!("{}:{}", std::iter::repeat(" ").take(depth*4).collect::<String>(), root.val );

    match root.l {
        Some(node) => {
            print_node(*node, depth + 1);
        }
        None => return,
    }
}

pub fn get_pyramid(fname: &str) -> Pyramid {

    let file = BufReader::new(File::open(fname).unwrap());

    file.lines()
        .map( |l| l.unwrap().split(char::is_whitespace)
             .map(|g| g.chars().collect::<String>().parse::<usize>().unwrap())
             .collect() )
        .collect()
}<commit_msg>memry intesive b-tree approach<commit_after>use std::fs::File;
use std::io::{BufRead, BufReader};
mod node;
use node::*;

type Pyramid = Vec<Vec<usize>>;

fn main() {
    // let pyramid = get_pyramid("pyramid.txt");
    let pyramid = get_pyramid("mini.txt");
    let mut root = Node { val: pyramid[0][0], l: None, r: None };

    // populate treeee

    populate_binary_tree(&mut root, 1, 0, 1, &pyramid, pyramid.len());

    // print_node(root, 0);

    let max_sum = max_path(root);

    println!("max sum: {}", max_sum);
}

use std::cmp;

fn max_path( root: Node ) -> usize {

    let r_max: usize;
    match root.r {
        Some(node) => {
            r_max = max_path(*node);
        }
        None => { r_max = 0; }
    }

    let l_max: usize;
    match root.l {
        Some(node) => {
            l_max = max_path(*node);
        }
        None => { l_max = 0; }
    }

    root.val + cmp::max(l_max, r_max)
}

fn populate_binary_tree(root: &mut Node, depth: usize, lidx: usize, ridx: usize, pyramid: &Pyramid, max_depth: usize) {

    if depth == max_depth {
        return
    }

    let mut l = Node { val: pyramid[depth][lidx], l: None, r: None };
    let mut r = Node { val: pyramid[depth][ridx], l: None, r: None };

    populate_binary_tree(&mut l, depth+1, lidx, ridx, pyramid, max_depth);
    populate_binary_tree(&mut r, depth+1, ridx, ridx + 1, pyramid, max_depth);

    root.l = Some(Box::new(l));
    root.r = Some(Box::new(r));
}

fn print_node( root: Node, depth: usize ) {

    match root.r {
        Some(node) => {
            print_node(*node, depth + 1);
        }
        None => {}
    }

    println!("{}:{}", std::iter::repeat(" ").take(depth*4).collect::<String>(), root.val );

    match root.l {
        Some(node) => {
            print_node(*node, depth + 1);
        }
        None => {}
    }
}

pub fn get_pyramid(fname: &str) -> Pyramid {

    let file = BufReader::new(File::open(fname).unwrap());

    file.lines()
        .map( |l| l.unwrap().split(char::is_whitespace)
             .map(|g| g.chars().collect::<String>().parse::<usize>().unwrap())
             .collect() )
        .collect()
}<|endoftext|>


<commit_before><commit_msg>micro-optimize Stats::is_empty()<commit_after><|endoftext|>


<commit_before><commit_msg>Move Borders documentation<commit_after><|endoftext|>