<commit_before>use core::ops::Deref;
use fake_adapter::FakeBluetoothAdapter;
use fake_service::FakeBluetoothGATTService;
use rustc_serialize::hex::FromHex;
use std::error::Error;
use std::sync::{Arc, Mutex};

#[derive(Clone, Debug)]
pub struct FakeBluetoothDevice {
    id: Arc<Mutex<String>>,
    adapter: Arc<FakeBluetoothAdapter>,
    address: Arc<Mutex<String>>,
    appearance: Arc<Mutex<u16>>,
    class: Arc<Mutex<u32>>,
    gatt_services: Arc<Mutex<Vec<Arc<FakeBluetoothGATTService>>>>,
    is_paired: Arc<Mutex<bool>>,
    is_connectable: Arc<Mutex<bool>>,
    is_connected: Arc<Mutex<bool>>,
    is_trusted: Arc<Mutex<bool>>,
    is_blocked: Arc<Mutex<bool>>,
    is_legacy_pairing: Arc<Mutex<bool>>,
    uuids: Arc<Mutex<Vec<String>>>,
    name: Arc<Mutex<String>>,
    icon: Arc<Mutex<String>>,
    alias: Arc<Mutex<String>>,
    product_version: Arc<Mutex<u32>>,
    rssi: Arc<Mutex<i16>>,
    tx_power: Arc<Mutex<i16>>,
    modalias: Arc<Mutex<String>>,
}

impl FakeBluetoothDevice {
    pub fn new(id: String,
               adapter: Arc<FakeBluetoothAdapter>,
               address: String,
               appearance: u16,
               class: u32,
               gatt_services: Vec<Arc<FakeBluetoothGATTService>>,
               is_paired: bool,
               is_connectable: bool,
               is_connected: bool,
               is_trusted: bool,
               is_blocked: bool,
               is_legacy_pairing: bool,
               uuids: Vec<String>,
               name: String,
               icon: String,
               alias: String,
               product_version: u32,
               rssi: i16,
               tx_power: i16,
               modalias: String)
               -> Arc<FakeBluetoothDevice> {
        if let Ok(existing_device) = adapter.get_device(id.clone()) {
            return existing_device;
        }
        let device = Arc::new(FakeBluetoothDevice{
            id: Arc::new(Mutex::new(id)),
            adapter: adapter.clone(),
            address: Arc::new(Mutex::new(address)),
            appearance: Arc::new(Mutex::new(appearance)),
            class: Arc::new(Mutex::new(class)),
            gatt_services: Arc::new(Mutex::new(gatt_services)),
            is_paired: Arc::new(Mutex::new(is_paired)),
            is_connectable: Arc::new(Mutex::new(is_connectable)),
            is_connected: Arc::new(Mutex::new(is_connected)),
            is_trusted: Arc::new(Mutex::new(is_trusted)),
            is_blocked: Arc::new(Mutex::new(is_blocked)),
            is_legacy_pairing: Arc::new(Mutex::new(is_legacy_pairing)),
            uuids: Arc::new(Mutex::new(uuids)),
            name: Arc::new(Mutex::new(name)),
            icon: Arc::new(Mutex::new(icon)),
            alias: Arc::new(Mutex::new(alias)),
            product_version: Arc::new(Mutex::new(product_version)),
            rssi: Arc::new(Mutex::new(rssi)),
            tx_power: Arc::new(Mutex::new(tx_power)),
            modalias: Arc::new(Mutex::new(modalias)),
        });
        let _ = adapter.add_device(device.clone());
        device
    }

    pub fn new_empty(adapter: Arc<FakeBluetoothAdapter>, device_id: String)
            -> Arc<FakeBluetoothDevice> {
        FakeBluetoothDevice::new(
            /*id*/ device_id,
            /*adapter*/ adapter,
            /*address*/ String::new(),
            /*appearance*/ 0,
            /*class*/ 0,
            /*gatt_services*/ vec!(),
            /*is_paired*/ false,
            /*is_connectable*/ false,
            /*is_connected*/ false,
            /*is_trusted*/ false,
            /*is_blocked*/ false,
            /*is_legacy_pairing*/ false,
            /*uuids*/ vec!(),
            /*name*/ String::new(),
            /*icon*/ String::new(),
            /*alias*/ String::new(),
            /*product_version*/ 0,
            /*rssi*/ 0,
            /*tx_power*/ 0,
            /*modalias*/ String::new(),
        )
    }

    make_getter!(get_id, id);

    make_setter!(set_id, id);

    pub fn get_adapter(&self) -> Result<Arc<FakeBluetoothAdapter>, Box<Error>> {
        Ok(self.adapter.clone())
    }

    /*pub fn set_adapter(&self, adapter: Arc<FakeBluetoothAdapter>) -> Result<(), Box<Error>> {
        Ok(self.adapter = adapter)
    }*/

    make_getter!(get_address, address, String);

    make_setter!(set_address, address, String);

    make_getter!(get_name, name, String);

    make_setter!(set_name, name, String);

    make_getter!(get_icon, icon, String);

    make_setter!(set_icon, icon, String);

    make_getter!(get_class, class, u32);

    make_setter!(set_class, class, u32);

    make_getter!(get_appearance, appearance, u16);

    make_setter!(set_appearance, appearance, u16);

    make_getter!(get_uuids, uuids, Vec<String>);

    make_setter!(set_uuids, uuids, Vec<String>);

    /*pub fn add_uuid(&self, uuid: String) -> Result<(), Box<Error>> {
        let mut uuids = try!(self.get_uuids());
        if uuids.contains(&uuid) {
            return Ok(())
        }
        uuids.push(uuid);
        self.set_uuids(uuids)
    }*/

    make_getter!(is_paired);

    make_setter!(set_paired, is_paired, bool);

    pub fn pair(&self) -> Result<(), Box<Error>> {
        self.set_paired(true)
    }

    pub fn cancel_pairing(&self) -> Result<(), Box<Error>> {
        self.set_paired(false)
    }

    make_getter!(is_connectable);

    make_setter!(set_connectable, is_connectable, bool);

    make_getter!(is_connected);

    make_setter!(set_connected, is_connected, bool);

    make_getter!(is_trusted);

    make_setter!(set_trusted, is_trusted, bool);

    make_getter!(is_blocked);

    make_setter!(set_blocked, is_blocked, bool);

    make_getter!(get_alias, alias, String);

    make_setter!(set_alias, alias, String);

    make_getter!(is_legacy_pairing);

    make_setter!(set_legacy_pairing, is_legacy_pairing, bool);

    pub fn get_modalias(&self) ->  Result<(String, u32, u32, u32), Box<Error>> {
        let cloned = self.modalias.clone();
        let modalias = match cloned.lock() {
            Ok(guard) => guard.deref().clone(),
            Err(_) => return Err(Box::from("Could not get the value.")),
        };

        let ids: Vec<&str> = modalias.split(":").collect();
        let source = String::from(ids[0]);
        let vendor = ids[1][1..5].from_hex().unwrap();
        let product = ids[1][6..10].from_hex().unwrap();
        let device = ids[1][11..15].from_hex().unwrap();

        Ok((source,
        (vendor[0] as u32) * 16 * 16 + (vendor[1] as u32),
        (product[0] as u32) * 16 * 16 + (product[1] as u32),
        (device[0] as u32) * 16 * 16 + (device[1] as u32)))
    }

    make_setter!(set_modalias, modalias, String);

    pub fn get_vendor_id_source(&self) -> Result<String, Box<Error>> {
        let (vendor_id_source,_,_,_) = try!(self.get_modalias());
        Ok(vendor_id_source)
    }

    pub fn get_vendor_id(&self) -> Result<u32, Box<Error>> {
        let (_,vendor_id,_,_) = try!(self.get_modalias());
        Ok(vendor_id)
    }

    pub fn get_product_id(&self) -> Result<u32, Box<Error>> {
        let (_,_,product_id,_) = try!(self.get_modalias());
        Ok(product_id)
    }

    pub fn get_device_id(&self) -> Result<u32, Box<Error>> {
        let (_,_,_,device_id) = try!(self.get_modalias());
        Ok(device_id)
    }

    make_getter!(get_rssi, rssi, i16);

    make_setter!(set_rssi, rssi, i16);

    make_getter!(get_tx_power, tx_power, i16);

    make_setter!(set_tx_power, tx_power, i16);

    make_getter!(get_gatt_services, gatt_services, Vec<Arc<FakeBluetoothGATTService>>);

    make_setter!(set_gatt_services, gatt_services, Vec<Arc<FakeBluetoothGATTService>>);

    pub fn get_gatt_service(&self, id: String) -> Result<Arc<FakeBluetoothGATTService>, Box<Error>> {
        let services = try!(self.get_gatt_services());
        for service in services {
            let service_id = service.get_id();
            if service_id == id {
                return Ok(service);
            }
        }
        Err(Box::from("No service exists with the given id."))
    }

    pub fn add_service(&self, service: Arc<FakeBluetoothGATTService>) -> Result<(), Box<Error>> {
        let cloned = self.gatt_services.clone();
        let mut gatt_services = match cloned.lock() {
            Ok(guard) => guard,
            Err(_) => return Err(Box::from("Could not get the value.")),
        };
        Ok(gatt_services.push(service))
    }

    pub fn connect_profile(&self, _uuid: String) -> Result<(), Box<Error>> {
        unimplemented!();
    }

    pub fn disconnect_profile(&self, _uuid: String) -> Result<(), Box<Error>> {
        unimplemented!();
    }

    pub fn connect(&self) -> Result<(), Box<Error>> {
        let is_connectable = try!(self.is_connectable());
        let is_connected = try!(self.is_connected());

        if is_connected {
            return Ok(());
        }
        if is_connectable {
            return self.set_connected(true);
        }
        return Err(Box::from("Could not connect to the device."));
    }

    pub fn disconnect(&self) -> Result<(), Box<Error>>{
        let is_connected = try!(self.is_connected());

        if is_connected {
            return self.set_connected(false);
        }
        return Err(Box::from("The device is not connected."));
    }
}
<commit_msg>device get_gatt_services modification<commit_after>use core::ops::Deref;
use fake_adapter::FakeBluetoothAdapter;
use fake_service::FakeBluetoothGATTService;
use rustc_serialize::hex::FromHex;
use std::error::Error;
use std::sync::{Arc, Mutex};

#[derive(Clone, Debug)]
pub struct FakeBluetoothDevice {
    id: Arc<Mutex<String>>,
    adapter: Arc<FakeBluetoothAdapter>,
    address: Arc<Mutex<String>>,
    appearance: Arc<Mutex<u16>>,
    class: Arc<Mutex<u32>>,
    gatt_services: Arc<Mutex<Vec<Arc<FakeBluetoothGATTService>>>>,
    is_paired: Arc<Mutex<bool>>,
    is_connectable: Arc<Mutex<bool>>,
    is_connected: Arc<Mutex<bool>>,
    is_trusted: Arc<Mutex<bool>>,
    is_blocked: Arc<Mutex<bool>>,
    is_legacy_pairing: Arc<Mutex<bool>>,
    uuids: Arc<Mutex<Vec<String>>>,
    name: Arc<Mutex<String>>,
    icon: Arc<Mutex<String>>,
    alias: Arc<Mutex<String>>,
    product_version: Arc<Mutex<u32>>,
    rssi: Arc<Mutex<i16>>,
    tx_power: Arc<Mutex<i16>>,
    modalias: Arc<Mutex<String>>,
}

impl FakeBluetoothDevice {
    pub fn new(id: String,
               adapter: Arc<FakeBluetoothAdapter>,
               address: String,
               appearance: u16,
               class: u32,
               gatt_services: Vec<Arc<FakeBluetoothGATTService>>,
               is_paired: bool,
               is_connectable: bool,
               is_connected: bool,
               is_trusted: bool,
               is_blocked: bool,
               is_legacy_pairing: bool,
               uuids: Vec<String>,
               name: String,
               icon: String,
               alias: String,
               product_version: u32,
               rssi: i16,
               tx_power: i16,
               modalias: String)
               -> Arc<FakeBluetoothDevice> {
        if let Ok(existing_device) = adapter.get_device(id.clone()) {
            return existing_device;
        }
        let device = Arc::new(FakeBluetoothDevice{
            id: Arc::new(Mutex::new(id)),
            adapter: adapter.clone(),
            address: Arc::new(Mutex::new(address)),
            appearance: Arc::new(Mutex::new(appearance)),
            class: Arc::new(Mutex::new(class)),
            gatt_services: Arc::new(Mutex::new(gatt_services)),
            is_paired: Arc::new(Mutex::new(is_paired)),
            is_connectable: Arc::new(Mutex::new(is_connectable)),
            is_connected: Arc::new(Mutex::new(is_connected)),
            is_trusted: Arc::new(Mutex::new(is_trusted)),
            is_blocked: Arc::new(Mutex::new(is_blocked)),
            is_legacy_pairing: Arc::new(Mutex::new(is_legacy_pairing)),
            uuids: Arc::new(Mutex::new(uuids)),
            name: Arc::new(Mutex::new(name)),
            icon: Arc::new(Mutex::new(icon)),
            alias: Arc::new(Mutex::new(alias)),
            product_version: Arc::new(Mutex::new(product_version)),
            rssi: Arc::new(Mutex::new(rssi)),
            tx_power: Arc::new(Mutex::new(tx_power)),
            modalias: Arc::new(Mutex::new(modalias)),
        });
        let _ = adapter.add_device(device.clone());
        device
    }

    pub fn new_empty(adapter: Arc<FakeBluetoothAdapter>, device_id: String)
            -> Arc<FakeBluetoothDevice> {
        FakeBluetoothDevice::new(
            /*id*/ device_id,
            /*adapter*/ adapter,
            /*address*/ String::new(),
            /*appearance*/ 0,
            /*class*/ 0,
            /*gatt_services*/ vec!(),
            /*is_paired*/ false,
            /*is_connectable*/ false,
            /*is_connected*/ false,
            /*is_trusted*/ false,
            /*is_blocked*/ false,
            /*is_legacy_pairing*/ false,
            /*uuids*/ vec!(),
            /*name*/ String::new(),
            /*icon*/ String::new(),
            /*alias*/ String::new(),
            /*product_version*/ 0,
            /*rssi*/ 0,
            /*tx_power*/ 0,
            /*modalias*/ String::new(),
        )
    }

    make_getter!(get_id, id);

    make_setter!(set_id, id);

    pub fn get_adapter(&self) -> Result<Arc<FakeBluetoothAdapter>, Box<Error>> {
        Ok(self.adapter.clone())
    }

    /*pub fn set_adapter(&self, adapter: Arc<FakeBluetoothAdapter>) -> Result<(), Box<Error>> {
        Ok(self.adapter = adapter)
    }*/

    make_getter!(get_address, address, String);

    make_setter!(set_address, address, String);

    make_getter!(get_name, name, String);

    make_setter!(set_name, name, String);

    make_getter!(get_icon, icon, String);

    make_setter!(set_icon, icon, String);

    make_getter!(get_class, class, u32);

    make_setter!(set_class, class, u32);

    make_getter!(get_appearance, appearance, u16);

    make_setter!(set_appearance, appearance, u16);

    make_getter!(get_uuids, uuids, Vec<String>);

    make_setter!(set_uuids, uuids, Vec<String>);

    /*pub fn add_uuid(&self, uuid: String) -> Result<(), Box<Error>> {
        let mut uuids = try!(self.get_uuids());
        if uuids.contains(&uuid) {
            return Ok(())
        }
        uuids.push(uuid);
        self.set_uuids(uuids)
    }*/

    make_getter!(is_paired);

    make_setter!(set_paired, is_paired, bool);

    pub fn pair(&self) -> Result<(), Box<Error>> {
        self.set_paired(true)
    }

    pub fn cancel_pairing(&self) -> Result<(), Box<Error>> {
        self.set_paired(false)
    }

    make_getter!(is_connectable);

    make_setter!(set_connectable, is_connectable, bool);

    make_getter!(is_connected);

    make_setter!(set_connected, is_connected, bool);

    make_getter!(is_trusted);

    make_setter!(set_trusted, is_trusted, bool);

    make_getter!(is_blocked);

    make_setter!(set_blocked, is_blocked, bool);

    make_getter!(get_alias, alias, String);

    make_setter!(set_alias, alias, String);

    make_getter!(is_legacy_pairing);

    make_setter!(set_legacy_pairing, is_legacy_pairing, bool);

    pub fn get_modalias(&self) ->  Result<(String, u32, u32, u32), Box<Error>> {
        let cloned = self.modalias.clone();
        let modalias = match cloned.lock() {
            Ok(guard) => guard.deref().clone(),
            Err(_) => return Err(Box::from("Could not get the value.")),
        };

        let ids: Vec<&str> = modalias.split(":").collect();
        let source = String::from(ids[0]);
        let vendor = ids[1][1..5].from_hex().unwrap();
        let product = ids[1][6..10].from_hex().unwrap();
        let device = ids[1][11..15].from_hex().unwrap();

        Ok((source,
        (vendor[0] as u32) * 16 * 16 + (vendor[1] as u32),
        (product[0] as u32) * 16 * 16 + (product[1] as u32),
        (device[0] as u32) * 16 * 16 + (device[1] as u32)))
    }

    make_setter!(set_modalias, modalias, String);

    pub fn get_vendor_id_source(&self) -> Result<String, Box<Error>> {
        let (vendor_id_source,_,_,_) = try!(self.get_modalias());
        Ok(vendor_id_source)
    }

    pub fn get_vendor_id(&self) -> Result<u32, Box<Error>> {
        let (_,vendor_id,_,_) = try!(self.get_modalias());
        Ok(vendor_id)
    }

    pub fn get_product_id(&self) -> Result<u32, Box<Error>> {
        let (_,_,product_id,_) = try!(self.get_modalias());
        Ok(product_id)
    }

    pub fn get_device_id(&self) -> Result<u32, Box<Error>> {
        let (_,_,_,device_id) = try!(self.get_modalias());
        Ok(device_id)
    }

    make_getter!(get_rssi, rssi, i16);

    make_setter!(set_rssi, rssi, i16);

    make_getter!(get_tx_power, tx_power, i16);

    make_setter!(set_tx_power, tx_power, i16);

    pub fn get_gatt_services(&self) -> Result<Vec<Arc<FakeBluetoothGATTService>>, Box<Error>> {
        if !(try!(self.is_connected())) {
            return Err(Box::from("Device not connected."));
        }

        let cloned = self.gatt_services.clone();
        let gatt_services = match cloned.lock() {
            Ok(guard) => guard.deref().clone(),
            Err(_) => return Err(Box::from("Could not get the value.")),
        };
        Ok(gatt_services)
    }

    make_setter!(set_gatt_services, gatt_services, Vec<Arc<FakeBluetoothGATTService>>);

    pub fn get_gatt_service(&self, id: String) -> Result<Arc<FakeBluetoothGATTService>, Box<Error>> {
        let services = try!(self.get_gatt_services());
        for service in services {
            let service_id = service.get_id();
            if service_id == id {
                return Ok(service);
            }
        }
        Err(Box::from("No service exists with the given id."))
    }

    pub fn add_service(&self, service: Arc<FakeBluetoothGATTService>) -> Result<(), Box<Error>> {
        let cloned = self.gatt_services.clone();
        let mut gatt_services = match cloned.lock() {
            Ok(guard) => guard,
            Err(_) => return Err(Box::from("Could not get the value.")),
        };
        Ok(gatt_services.push(service))
    }

    pub fn connect_profile(&self, _uuid: String) -> Result<(), Box<Error>> {
        unimplemented!();
    }

    pub fn disconnect_profile(&self, _uuid: String) -> Result<(), Box<Error>> {
        unimplemented!();
    }

    pub fn connect(&self) -> Result<(), Box<Error>> {
        let is_connectable = try!(self.is_connectable());
        let is_connected = try!(self.is_connected());

        if is_connected {
            return Ok(());
        }
        if is_connectable {
            return self.set_connected(true);
        }
        return Err(Box::from("Could not connect to the device."));
    }

    pub fn disconnect(&self) -> Result<(), Box<Error>>{
        let is_connected = try!(self.is_connected());

        if is_connected {
            return self.set_connected(false);
        }
        return Err(Box::from("The device is not connected."));
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::collections::hash_map::{HashMap, Entry};
use std::borrow::BorrowMut;
use gl;
use gl::types::*;
use context::ContextOf;
use renderbuffer::{Renderbuffer, RenderbufferTarget};
use texture::{Texture, TextureType, ImageTargetType,
              Texture2d, Tx2dImageTarget};
use types::{BufferBits, GLError, GLFramebufferError};

pub struct Framebuffer {
    gl_id: GLuint
}

impl Framebuffer {
    pub unsafe fn from_gl(id: GLuint) -> Self {
        Framebuffer { gl_id: id }
    }

    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Framebuffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteFramebuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

enum BuilderAttachment<'a> {
    Texture2d(&'a mut Texture2d, i32),
    Renderbuffer(&'a mut Renderbuffer)
}

pub struct FramebufferBuilder<'a, AB, EAB, P, FB, RB, TU>
    where  AB: 'a,
          EAB: 'a,
            P: 'a,
           FB: 'a + BorrowMut<FramebufferBinder>,
           RB: 'a,
           TU: 'a
{
    gl: &'a mut ContextOf<AB, EAB, P, FB, RB, TU>,
    attachments: HashMap<FramebufferAttachment, BuilderAttachment<'a>>
}

impl<'a, AB, EAB, P, FB, RB, TU> FramebufferBuilder<'a, AB, EAB, P, FB, RB, TU>
    where  AB: 'a,
          EAB: 'a,
            P: 'a,
           FB: 'a + BorrowMut<FramebufferBinder>,
           RB: 'a,
           TU: 'a
{
    fn new(gl: &'a mut ContextOf<AB, EAB, P, FB, RB, TU>) -> Self {
        FramebufferBuilder {
            gl: gl,
            attachments: HashMap::new()
        }
    }

    pub fn texture_2d(mut self,
                      attachment: FramebufferAttachment,
                      texture: &'a mut Texture2d,
                      level: i32)
        -> Self
    {
        let attached = BuilderAttachment::Texture2d(texture, level);
        match self.attachments.entry(attachment) {
            Entry::Occupied(mut e) => { e.insert(attached); },
            Entry::Vacant(e) => { e.insert(attached); }
        };

        self
    }

    pub fn renderbuffer(mut self,
                        attachment: FramebufferAttachment,
                        renderbuffer: &'a mut Renderbuffer)
        -> Self
    {
        let attached = BuilderAttachment::Renderbuffer(renderbuffer);
        match self.attachments.entry(attachment) {
            Entry::Occupied(mut e) => { e.insert(attached); },
            Entry::Vacant(e) => { e.insert(attached); }
        };

        self
    }

    pub fn try_unwrap(self) -> Result<Framebuffer, GLError> {
        let mut fbo = unsafe { self.gl.gen_framebuffer() };
        let (mut gl_fbo, _) = self.gl.bind_framebuffer(&mut fbo);

        for (attachment, attached) in self.attachments.into_iter() {
            match attached {
                BuilderAttachment::Texture2d(texture, level) => {
                    gl_fbo.texture_2d(attachment,
                                      Tx2dImageTarget::Texture2d,
                                      texture,
                                      level);
                },
                BuilderAttachment::Renderbuffer(renderbuffer) => {
                    gl_fbo.renderbuffer(attachment, renderbuffer);
                }
            }
        }

        match gl_fbo.check_framebuffer_status() {
            Some(err) => { Err(err.into()) },
            None => { Ok(fbo) }
        }
    }

    pub fn unwrap(self) -> Framebuffer {
        self.try_unwrap().unwrap()
    }
}

impl<AB, EAB, P, FB, RB, TU> ContextOf<AB, EAB, P, FB, RB, TU> {
    pub fn build_framebuffer<'a>(&'a mut self)
        -> FramebufferBuilder<'a, AB, EAB, P, FB, RB, TU>
        where  AB: 'a,
              EAB: 'a,
                P: 'a,
               FB: 'a + BorrowMut<FramebufferBinder>,
               RB: 'a,
               TU: 'a
    {
        FramebufferBuilder::new(self)
    }

    pub unsafe fn gen_framebuffer(&self) -> Framebuffer {
        let mut id : GLuint = 0;

        gl::GenFramebuffers(1, &mut id as *mut GLuint);
        dbg_gl_sanity_check! {
            GLError::InvalidValue => "`n` is negative",
            _ => "Unknown error"
        }

        Framebuffer {
            gl_id: id
        }
    }

    pub fn bind_framebuffer<'a>(&'a mut self, framebuffer: &mut Framebuffer)
        -> (
            FramebufferBinding<'a>,
            ContextOf<&'a mut AB,
                      &'a mut EAB,
                      &'a mut P,
                      (),
                      &'a mut RB,
                      &'a mut TU>
        )
        where FB: BorrowMut<FramebufferBinder>
    {
        let (framebuffer_binder, gl) = self.split_framebuffer_mut();
        (framebuffer_binder.bind(framebuffer), gl)
    }
}

gl_enum! {
    pub gl_enum FramebufferTarget {
        Framebuffer as FRAMEBUFFER = gl::FRAMEBUFFER
    }
}

gl_enum! {
    pub gl_enum FramebufferAttachment {
        ColorAttachment0 as COLOR_ATTACHMENT0 = gl::COLOR_ATTACHMENT0,
        DepthAttachment as DEPTH_ATTACHMENT = gl::DEPTH_ATTACHMENT,
        StencilAttachment as STENCIL_ATTACHMENT = gl::STENCIL_ATTACHMENT
    }
}

pub struct FramebufferBinding<'a> {
    phantom: PhantomData<&'a mut Framebuffer>
}

impl<'a> FramebufferBinding<'a> {
    fn target(&self) -> FramebufferTarget {
        FramebufferTarget::Framebuffer
    }

    pub fn check_framebuffer_status(&self) -> Option<GLFramebufferError> {
        unsafe {
            match gl::CheckFramebufferStatus(self.target().gl_enum()) {
                gl::FRAMEBUFFER_INCOMPLETE_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteAttachment)
                },
                // gl::FRAMEBUFFER_INCOMPLETE_DIMENSIONS => {
                //     Some(GLFramebufferError::IncompleteDimensions)
                // },
                gl::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteMissingAttachment)
                },
                gl::FRAMEBUFFER_UNSUPPORTED => {
                    Some(GLFramebufferError::Unsupported)
                },
                _ => { None }
            }
        }
    }

    pub fn renderbuffer(&mut self,
                        attachment: FramebufferAttachment,
                        renderbuffer: &mut Renderbuffer)
    {
        let renderbuffer_target = RenderbufferTarget::Renderbuffer;
        unsafe {
            gl::FramebufferRenderbuffer(self.target().gl_enum(),
                                        attachment.gl_enum(),
                                        renderbuffer_target.gl_enum(),
                                        renderbuffer.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not a valid attachment point, or `renderbuffer` is not `GL_RENDERBUFFER` and `renderbuffer` is not 0",
                GLError::InvalidOperation => "Framebuffer 0 is bound, or `renderbuffer` is neither 0 nor the name of an existing renderbuffer object",
                _ => "Unknown error"
            }
        }
    }

    pub fn texture_2d<T, I>(&mut self,
                            attachment: FramebufferAttachment,
                            tex_target: I,
                            texture: &mut Texture<T>,
                            level: i32)
        where T: TextureType, I: Into<T::ImageTargetType>
    {
        debug_assert!(level == 0);

        unsafe {
            gl::FramebufferTexture2D(self.target().gl_enum(),
                                     attachment.gl_enum(),
                                     tex_target.into().gl_enum(),
                                     texture.gl_id(),
                                     level as GLint);
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not an accepted attachment point, or `textarget` is not an accepted texture target and texture is not 0",
                GLError::InvalidValue => "`level` is not 0 and `texture` is not 0",
                GLError::InvalidOperation => "Framebuffer object 0 is bound, `texture` is neither 0 nor the name of an existing texture object, or `textarget` is not a valid target for `texture`",
                _ => "Unknown error"
            }
        }
    }

    pub fn clear(&mut self, buffers: BufferBits) {
        unsafe {
            gl::Clear(buffers.bits());
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`mask` includes a bit other than an allowed value",
                _ => "Unkown error"
            }
        }
    }
}

pub struct FramebufferBinder;
impl FramebufferBinder {
    pub unsafe fn current_binding(&mut self) -> FramebufferBinding {
        FramebufferBinding { phantom: PhantomData }
    }

    pub fn bind(&mut self, fbo: &mut Framebuffer) -> FramebufferBinding {
        let binding = FramebufferBinding { phantom: PhantomData };
        unsafe {
            gl::BindFramebuffer(binding.target().gl_enum(), fbo.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`",
                _ => "Unknown error"
            }
        }
        binding
    }
}
<commit_msg>Add `ContextOf.current_framebuffer_binding()`<commit_after>use std::marker::PhantomData;
use std::collections::hash_map::{HashMap, Entry};
use std::borrow::BorrowMut;
use gl;
use gl::types::*;
use context::ContextOf;
use renderbuffer::{Renderbuffer, RenderbufferTarget};
use texture::{Texture, TextureType, ImageTargetType,
              Texture2d, Tx2dImageTarget};
use types::{BufferBits, GLError, GLFramebufferError};

pub struct Framebuffer {
    gl_id: GLuint
}

impl Framebuffer {
    pub unsafe fn from_gl(id: GLuint) -> Self {
        Framebuffer { gl_id: id }
    }

    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Framebuffer {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteFramebuffers(1, &self.gl_id as *const GLuint);
        }
    }
}

enum BuilderAttachment<'a> {
    Texture2d(&'a mut Texture2d, i32),
    Renderbuffer(&'a mut Renderbuffer)
}

pub struct FramebufferBuilder<'a, AB, EAB, P, FB, RB, TU>
    where  AB: 'a,
          EAB: 'a,
            P: 'a,
           FB: 'a + BorrowMut<FramebufferBinder>,
           RB: 'a,
           TU: 'a
{
    gl: &'a mut ContextOf<AB, EAB, P, FB, RB, TU>,
    attachments: HashMap<FramebufferAttachment, BuilderAttachment<'a>>
}

impl<'a, AB, EAB, P, FB, RB, TU> FramebufferBuilder<'a, AB, EAB, P, FB, RB, TU>
    where  AB: 'a,
          EAB: 'a,
            P: 'a,
           FB: 'a + BorrowMut<FramebufferBinder>,
           RB: 'a,
           TU: 'a
{
    fn new(gl: &'a mut ContextOf<AB, EAB, P, FB, RB, TU>) -> Self {
        FramebufferBuilder {
            gl: gl,
            attachments: HashMap::new()
        }
    }

    pub fn texture_2d(mut self,
                      attachment: FramebufferAttachment,
                      texture: &'a mut Texture2d,
                      level: i32)
        -> Self
    {
        let attached = BuilderAttachment::Texture2d(texture, level);
        match self.attachments.entry(attachment) {
            Entry::Occupied(mut e) => { e.insert(attached); },
            Entry::Vacant(e) => { e.insert(attached); }
        };

        self
    }

    pub fn renderbuffer(mut self,
                        attachment: FramebufferAttachment,
                        renderbuffer: &'a mut Renderbuffer)
        -> Self
    {
        let attached = BuilderAttachment::Renderbuffer(renderbuffer);
        match self.attachments.entry(attachment) {
            Entry::Occupied(mut e) => { e.insert(attached); },
            Entry::Vacant(e) => { e.insert(attached); }
        };

        self
    }

    pub fn try_unwrap(self) -> Result<Framebuffer, GLError> {
        let mut fbo = unsafe { self.gl.gen_framebuffer() };
        let (mut gl_fbo, _) = self.gl.bind_framebuffer(&mut fbo);

        for (attachment, attached) in self.attachments.into_iter() {
            match attached {
                BuilderAttachment::Texture2d(texture, level) => {
                    gl_fbo.texture_2d(attachment,
                                      Tx2dImageTarget::Texture2d,
                                      texture,
                                      level);
                },
                BuilderAttachment::Renderbuffer(renderbuffer) => {
                    gl_fbo.renderbuffer(attachment, renderbuffer);
                }
            }
        }

        match gl_fbo.check_framebuffer_status() {
            Some(err) => { Err(err.into()) },
            None => { Ok(fbo) }
        }
    }

    pub fn unwrap(self) -> Framebuffer {
        self.try_unwrap().unwrap()
    }
}

impl<AB, EAB, P, FB, RB, TU> ContextOf<AB, EAB, P, FB, RB, TU> {
    pub fn build_framebuffer<'a>(&'a mut self)
        -> FramebufferBuilder<'a, AB, EAB, P, FB, RB, TU>
        where  AB: 'a,
              EAB: 'a,
                P: 'a,
               FB: 'a + BorrowMut<FramebufferBinder>,
               RB: 'a,
               TU: 'a
    {
        FramebufferBuilder::new(self)
    }

    pub unsafe fn gen_framebuffer(&self) -> Framebuffer {
        let mut id : GLuint = 0;

        gl::GenFramebuffers(1, &mut id as *mut GLuint);
        dbg_gl_sanity_check! {
            GLError::InvalidValue => "`n` is negative",
            _ => "Unknown error"
        }

        Framebuffer {
            gl_id: id
        }
    }

    pub fn bind_framebuffer<'a>(&'a mut self, framebuffer: &mut Framebuffer)
        -> (
            FramebufferBinding<'a>,
            ContextOf<&'a mut AB,
                      &'a mut EAB,
                      &'a mut P,
                      (),
                      &'a mut RB,
                      &'a mut TU>
        )
        where FB: BorrowMut<FramebufferBinder>
    {
        let (framebuffer_binder, gl) = self.split_framebuffer_mut();
        (framebuffer_binder.bind(framebuffer), gl)
    }

    pub unsafe fn current_framebuffer_binding(&mut self) -> FramebufferBinding
        where FB: BorrowMut<FramebufferBinder>
    {
        self.framebuffer.borrow_mut().current_binding()
    }
}

gl_enum! {
    pub gl_enum FramebufferTarget {
        Framebuffer as FRAMEBUFFER = gl::FRAMEBUFFER
    }
}

gl_enum! {
    pub gl_enum FramebufferAttachment {
        ColorAttachment0 as COLOR_ATTACHMENT0 = gl::COLOR_ATTACHMENT0,
        DepthAttachment as DEPTH_ATTACHMENT = gl::DEPTH_ATTACHMENT,
        StencilAttachment as STENCIL_ATTACHMENT = gl::STENCIL_ATTACHMENT
    }
}

pub struct FramebufferBinding<'a> {
    phantom: PhantomData<&'a mut Framebuffer>
}

impl<'a> FramebufferBinding<'a> {
    fn target(&self) -> FramebufferTarget {
        FramebufferTarget::Framebuffer
    }

    pub fn check_framebuffer_status(&self) -> Option<GLFramebufferError> {
        unsafe {
            match gl::CheckFramebufferStatus(self.target().gl_enum()) {
                gl::FRAMEBUFFER_INCOMPLETE_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteAttachment)
                },
                // gl::FRAMEBUFFER_INCOMPLETE_DIMENSIONS => {
                //     Some(GLFramebufferError::IncompleteDimensions)
                // },
                gl::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT => {
                    Some(GLFramebufferError::IncompleteMissingAttachment)
                },
                gl::FRAMEBUFFER_UNSUPPORTED => {
                    Some(GLFramebufferError::Unsupported)
                },
                _ => { None }
            }
        }
    }

    pub fn renderbuffer(&mut self,
                        attachment: FramebufferAttachment,
                        renderbuffer: &mut Renderbuffer)
    {
        let renderbuffer_target = RenderbufferTarget::Renderbuffer;
        unsafe {
            gl::FramebufferRenderbuffer(self.target().gl_enum(),
                                        attachment.gl_enum(),
                                        renderbuffer_target.gl_enum(),
                                        renderbuffer.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not a valid attachment point, or `renderbuffer` is not `GL_RENDERBUFFER` and `renderbuffer` is not 0",
                GLError::InvalidOperation => "Framebuffer 0 is bound, or `renderbuffer` is neither 0 nor the name of an existing renderbuffer object",
                _ => "Unknown error"
            }
        }
    }

    pub fn texture_2d<T, I>(&mut self,
                            attachment: FramebufferAttachment,
                            tex_target: I,
                            texture: &mut Texture<T>,
                            level: i32)
        where T: TextureType, I: Into<T::ImageTargetType>
    {
        debug_assert!(level == 0);

        unsafe {
            gl::FramebufferTexture2D(self.target().gl_enum(),
                                     attachment.gl_enum(),
                                     tex_target.into().gl_enum(),
                                     texture.gl_id(),
                                     level as GLint);
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`, `attachment` is not an accepted attachment point, or `textarget` is not an accepted texture target and texture is not 0",
                GLError::InvalidValue => "`level` is not 0 and `texture` is not 0",
                GLError::InvalidOperation => "Framebuffer object 0 is bound, `texture` is neither 0 nor the name of an existing texture object, or `textarget` is not a valid target for `texture`",
                _ => "Unknown error"
            }
        }
    }

    pub fn clear(&mut self, buffers: BufferBits) {
        unsafe {
            gl::Clear(buffers.bits());
            dbg_gl_sanity_check! {
                GLError::InvalidValue => "`mask` includes a bit other than an allowed value",
                _ => "Unkown error"
            }
        }
    }
}

pub struct FramebufferBinder;
impl FramebufferBinder {
    pub unsafe fn current_binding(&mut self) -> FramebufferBinding {
        FramebufferBinding { phantom: PhantomData }
    }

    pub fn bind(&mut self, fbo: &mut Framebuffer) -> FramebufferBinding {
        let binding = FramebufferBinding { phantom: PhantomData };
        unsafe {
            gl::BindFramebuffer(binding.target().gl_enum(), fbo.gl_id());
            dbg_gl_sanity_check! {
                GLError::InvalidEnum => "`target` is not `GL_FRAMEBUFFER`",
                _ => "Unknown error"
            }
        }
        binding
    }
}
<|endoftext|>


<commit_before>use std::ptr::null;
use libc::{c_int, c_char, c_double};
use sync::mutex::{StaticMutex, MUTEX_INIT};
use utils::_string;

#[link(name="gdal")]
extern {
    fn OGRRegisterAll();
    fn OGROpen(pszName: *const c_char, bUpdate: c_int, pahDriverList: *const ()) -> *const ();
    fn OGR_DS_GetLayerCount(hDS: *const ()) -> c_int;
    fn OGR_DS_Destroy(hDataSource: *const ());
    fn OGR_DS_GetLayer(hDS: *const (), iLayer: c_int) -> *const ();
    fn OGR_L_GetLayerDefn(hLayer: *const ()) -> *const ();
    fn OGR_L_GetNextFeature(hLayer: *const ()) -> *const ();
    fn OGR_FD_GetFieldCount(hDefn: *const ()) -> c_int;
    fn OGR_FD_GetFieldDefn(hDefn: *const (), iField: c_int) -> *const ();
    fn OGR_F_GetFieldIndex(hFeat: *const (), pszName: *const c_char) -> c_int;
    fn OGR_F_GetFieldDefnRef(hFeat: *const (), i: c_int) -> *const ();
    fn OGR_F_GetFieldAsString(hFeat: *const (), iField: c_int) -> *const c_char;
    fn OGR_F_GetFieldAsDouble(hFeat: *const (), iField: c_int) -> c_double;
    fn OGR_F_GetGeometryRef(hFeat: *const ()) -> *const ();
    fn OGR_F_Destroy(hFeat: *const ());
    fn OGR_G_ExportToWkt(hGeom: *const (), ppszSrcText: *const *const c_char) -> c_int;
    fn OGR_G_ExportToJson(hGeometry: *const ()) -> *const c_char;
    fn OGR_Fld_GetNameRef(hDefn: *const ()) -> *const c_char;
    fn OGR_Fld_GetType(hDefn: *const ()) -> c_int;
    fn OGRFree(ptr: *const ());
    fn VSIFree(ptr: *const ());
}

static OFTInteger:        c_int = 0;
static OFTIntegerList:    c_int = 1;
static OFTReal:           c_int = 2;
static OFTRealList:       c_int = 3;
static OFTString:         c_int = 4;
static OFTStringList:     c_int = 5;
static OFTWideString:     c_int = 6;
static OFTWideStringList: c_int = 7;
static OFTBinary:         c_int = 8;
static OFTDate:           c_int = 9;
static OFTTime:           c_int = 10;
static OFTDateTime:       c_int = 11;

static mut LOCK: StaticMutex = MUTEX_INIT;
static mut registered_drivers: bool = false;

fn register_drivers() {
    unsafe {
        let _g = LOCK.lock();
        if ! registered_drivers {
            OGRRegisterAll();
            registered_drivers = true;
        }
    }
}

pub struct VectorDataset {
    c_dataset: *const (),
}

impl VectorDataset {
    pub fn layer_count(&self) -> int {
        return unsafe { OGR_DS_GetLayerCount(self.c_dataset) } as int;
    }

    pub fn layer<'a>(&'a self, idx: int) -> Option<Layer<'a>> {
        let c_layer = unsafe { OGR_DS_GetLayer(self.c_dataset, idx as c_int) };
        return match c_layer.is_null() {
            true  => None,
            false => Some(Layer{vector_dataset: self, c_layer: c_layer}),
        };
    }
}

impl Drop for VectorDataset {
    fn drop(&mut self) {
        unsafe { OGR_DS_Destroy(self.c_dataset); }
    }
}

pub struct Layer<'a> {
    vector_dataset: &'a VectorDataset,
    c_layer: *const (),
}

impl<'a> Layer<'a> {
    pub fn fields<'a>(&'a self) -> FieldIterator<'a> {
        let c_feature_defn = unsafe { OGR_L_GetLayerDefn(self.c_layer) };
        let total = unsafe { OGR_FD_GetFieldCount(c_feature_defn) } as int;
        return FieldIterator{
            layer: self,
            c_feature_defn: c_feature_defn,
            next_id: 0,
            total: total
        };
    }

    pub fn features<'a>(&'a self) -> FeatureIterator<'a> {
        return FeatureIterator{layer: self};
    }
}

pub struct FieldIterator<'a> {
    layer: &'a Layer<'a>,
    c_feature_defn: *const (),
    next_id: int,
    total: int,
}

impl<'a> Iterator<Field<'a>> for FieldIterator<'a> {
    #[inline]
    fn next(&mut self) -> Option<Field<'a>> {
        if self.next_id == self.total {
            return None;
        }
        let field = Field{
            layer: self.layer,
            c_field_defn: unsafe { OGR_FD_GetFieldDefn(
                self.c_feature_defn,
                self.next_id as c_int
            ) }
        };
        self.next_id += 1;
        return Some(field);
    }
}

pub struct Field<'a> {
    layer: &'a Layer<'a>,
    c_field_defn: *const (),
}

impl<'a> Field<'a> {
    pub fn name(&'a self) -> String {
        let rv = unsafe { OGR_Fld_GetNameRef(self.c_field_defn) };
        return _string(rv);
    }
}

pub struct FeatureIterator<'a> {
    layer: &'a Layer<'a>,
}

impl<'a> Iterator<Feature<'a>> for FeatureIterator<'a> {
    #[inline]
    fn next(&mut self) -> Option<Feature<'a>> {
        let c_feature = unsafe { OGR_L_GetNextFeature(self.layer.c_layer) };
        return match c_feature.is_null() {
            true  => None,
            false => Some(Feature{layer: self.layer, c_feature: c_feature}),
        };
    }
}

pub struct Feature<'a> {
    layer: &'a Layer<'a>,
    c_feature: *const (),
}

impl<'a> Feature<'a> {
    pub fn field(&self, name: String) -> Option<FieldValue> {
        return name.with_c_str(|c_name| unsafe {
            let field_id = OGR_F_GetFieldIndex(self.c_feature, c_name);
            if field_id == -1 {
                return None;
            }
            let field_defn = OGR_F_GetFieldDefnRef(self.c_feature, field_id);
            let field_type = OGR_Fld_GetType(field_defn);
            return match field_type {
                OFTString => {
                    let rv = OGR_F_GetFieldAsString(self.c_feature, field_id);
                    return Some(StringValue(_string(rv)));
                },
                OFTReal => {
                    let rv = OGR_F_GetFieldAsDouble(self.c_feature, field_id);
                    return Some(RealValue(rv as f64));
                },
                _ => fail!("Unknown field type {}", field_type)
            }
        });
    }

    pub fn wkt(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_wkt: *const c_char = null();
            OGR_G_ExportToWkt(c_geom, &c_wkt);
            let wkt = _string(c_wkt);
            OGRFree(c_wkt as *const ());
            return wkt;
        }
    }

    pub fn json(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_json = OGR_G_ExportToJson(c_geom);
            let json = _string(c_json);
            VSIFree(c_json as *const ());
            return json;
        }
    }
}

#[unsafe_destructor]
impl<'a> Drop for Feature<'a> {
    fn drop(&mut self) {
        unsafe { OGR_F_Destroy(self.c_feature); }
    }
}

pub fn open(path: &Path) -> Option<VectorDataset> {
    register_drivers();
    let filename = path.as_str().unwrap();
    let c_dataset = filename.with_c_str(|c_filename| {
        return unsafe { OGROpen(c_filename, 0, null()) };
    });
    return match c_dataset.is_null() {
        true  => None,
        false => Some(VectorDataset{c_dataset: c_dataset}),
    };
}

pub enum FieldValue {
    StringValue(String),
    RealValue(f64),
}

impl FieldValue {
    pub fn as_string(self) -> String {
        match self { StringValue(rv) => rv, _ => fail!("not a StringValue") }
    }

    pub fn as_real(self) -> f64 {
        match self { RealValue(rv) => rv, _ => fail!("not a RealValue") }
    }
}

#[cfg(test)]
mod test {
    use std::os::getenv;
    use std::path::Path;
    use super::{Feature, FeatureIterator, open};

    fn fixture_path(name: &str) -> Path {
        let envvar = "RUST_GDAL_TEST_FIXTURES";
        let fixtures = match getenv(envvar) {
            Some(p) => Path::new(p),
            None => fail!("Environment variable {} not set", envvar)
        };
        let rv = fixtures.join(name);
        return rv;
    }

    fn assert_almost_eq(a: f64, b: f64) {
        let f: f64 = a / b;
        assert!(f < 1.00001);
        assert!(f > 0.99999);
    }

    #[test]
    fn test_layer_count() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        assert_eq!(ds.layer_count(), 1);
    }

    fn with_features(fixture: &str, f: |FeatureIterator|) {
        let ds = open(&fixture_path(fixture)).unwrap();
        let layer = ds.layer(0).unwrap();
        f(layer.features());
    }

    fn with_first_feature(fixture: &str, f: |Feature|) {
        with_features(fixture, |mut features| f(features.next().unwrap()));
    }

    #[test]
    fn test_iterate_features() {
        with_features("roads.geojson", |mut features| {
            let feature_vec: Vec<Feature> = features.collect();
            assert_eq!(feature_vec.len(), 21);
        });
    }

    #[test]
    fn test_string_field() {
        with_features("roads.geojson", |mut features| {
            let feature = features.next().unwrap();
            assert_eq!(feature.field("highway".to_string())
                              .unwrap()
                              .as_string(),
                       "footway".to_string());
            assert_eq!(
                features.filter(|field| {
                    let highway = field.field("highway".to_string())
                                       .unwrap()
                                       .as_string();
                    highway == "residential".to_string() })
                    .count(),
                2);
        });
    }

    #[test]
    fn test_float_field() {
        with_first_feature("roads.geojson", |feature| {
            assert_almost_eq(
                feature.field("sort_key".to_string())
                       .unwrap()
                       .as_real(),
                -9.0
            );
        });
    }

    #[test]
    fn test_missing_field() {
        with_first_feature("roads.geojson", |feature| {
            assert!(feature.field("no such field".to_string()).is_none());
        });
    }

    #[test]
    fn test_wkt() {
        with_first_feature("roads.geojson", |feature| {
            let wkt = feature.wkt();
            let wkt_ok = format!("{}{}",
                "LINESTRING (26.1019276 44.4302748,",
                "26.1019382 44.4303191,26.1020002 44.4304202)"
                ).to_string();
            assert_eq!(wkt, wkt_ok);
        });
    }

    #[test]
    fn test_json() {
        with_first_feature("roads.geojson", |feature| {
            let json = feature.json();
            let json_ok = format!("{}{}{}{}",
                "{ \"type\": \"LineString\", \"coordinates\": [ ",
                "[ 26.1019276, 44.4302748 ], ",
                "[ 26.1019382, 44.4303191 ], ",
                "[ 26.1020002, 44.4304202 ] ] }"
                ).to_string();
            assert_eq!(json, json_ok);
        });
    }

    #[test]
    fn test_schema() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.layer(0).unwrap();
        let name_list: Vec<String> = layer
            .fields()
            .map(|f| f.name())
            .collect();
        let ok_names = vec!("kind", "sort_key", "is_link", "is_tunnel",
                        "is_bridge", "railway", "highway")
                       .iter().map(|s| s.to_string()).collect();
        assert_eq!(name_list, ok_names);
    }
}
<commit_msg>change constants to uppercase<commit_after>use std::ptr::null;
use libc::{c_int, c_char, c_double};
use sync::mutex::{StaticMutex, MUTEX_INIT};
use utils::_string;

#[link(name="gdal")]
extern {
    fn OGRRegisterAll();
    fn OGROpen(pszName: *const c_char, bUpdate: c_int, pahDriverList: *const ()) -> *const ();
    fn OGR_DS_GetLayerCount(hDS: *const ()) -> c_int;
    fn OGR_DS_Destroy(hDataSource: *const ());
    fn OGR_DS_GetLayer(hDS: *const (), iLayer: c_int) -> *const ();
    fn OGR_L_GetLayerDefn(hLayer: *const ()) -> *const ();
    fn OGR_L_GetNextFeature(hLayer: *const ()) -> *const ();
    fn OGR_FD_GetFieldCount(hDefn: *const ()) -> c_int;
    fn OGR_FD_GetFieldDefn(hDefn: *const (), iField: c_int) -> *const ();
    fn OGR_F_GetFieldIndex(hFeat: *const (), pszName: *const c_char) -> c_int;
    fn OGR_F_GetFieldDefnRef(hFeat: *const (), i: c_int) -> *const ();
    fn OGR_F_GetFieldAsString(hFeat: *const (), iField: c_int) -> *const c_char;
    fn OGR_F_GetFieldAsDouble(hFeat: *const (), iField: c_int) -> c_double;
    fn OGR_F_GetGeometryRef(hFeat: *const ()) -> *const ();
    fn OGR_F_Destroy(hFeat: *const ());
    fn OGR_G_ExportToWkt(hGeom: *const (), ppszSrcText: *const *const c_char) -> c_int;
    fn OGR_G_ExportToJson(hGeometry: *const ()) -> *const c_char;
    fn OGR_Fld_GetNameRef(hDefn: *const ()) -> *const c_char;
    fn OGR_Fld_GetType(hDefn: *const ()) -> c_int;
    fn OGRFree(ptr: *const ());
    fn VSIFree(ptr: *const ());
}

static OFT_INTEGER:          c_int = 0;
static OFT_INTEGER_LIST:     c_int = 1;
static OFT_REAL:             c_int = 2;
static OFT_REAL_LIST:        c_int = 3;
static OFT_STRING:           c_int = 4;
static OFT_STRING_LIST:      c_int = 5;
static OFT_WIDE_STRING:      c_int = 6;
static OFT_WIDE_STRING_LIST: c_int = 7;
static OFT_BINARY:           c_int = 8;
static OFT_DATE:             c_int = 9;
static OFT_TIME:             c_int = 10;
static OFT_DATE_TIME:        c_int = 11;

static mut LOCK: StaticMutex = MUTEX_INIT;
static mut registered_drivers: bool = false;

fn register_drivers() {
    unsafe {
        let _g = LOCK.lock();
        if ! registered_drivers {
            OGRRegisterAll();
            registered_drivers = true;
        }
    }
}

pub struct VectorDataset {
    c_dataset: *const (),
}

impl VectorDataset {
    pub fn layer_count(&self) -> int {
        return unsafe { OGR_DS_GetLayerCount(self.c_dataset) } as int;
    }

    pub fn layer<'a>(&'a self, idx: int) -> Option<Layer<'a>> {
        let c_layer = unsafe { OGR_DS_GetLayer(self.c_dataset, idx as c_int) };
        return match c_layer.is_null() {
            true  => None,
            false => Some(Layer{vector_dataset: self, c_layer: c_layer}),
        };
    }
}

impl Drop for VectorDataset {
    fn drop(&mut self) {
        unsafe { OGR_DS_Destroy(self.c_dataset); }
    }
}

pub struct Layer<'a> {
    vector_dataset: &'a VectorDataset,
    c_layer: *const (),
}

impl<'a> Layer<'a> {
    pub fn fields<'a>(&'a self) -> FieldIterator<'a> {
        let c_feature_defn = unsafe { OGR_L_GetLayerDefn(self.c_layer) };
        let total = unsafe { OGR_FD_GetFieldCount(c_feature_defn) } as int;
        return FieldIterator{
            layer: self,
            c_feature_defn: c_feature_defn,
            next_id: 0,
            total: total
        };
    }

    pub fn features<'a>(&'a self) -> FeatureIterator<'a> {
        return FeatureIterator{layer: self};
    }
}

pub struct FieldIterator<'a> {
    layer: &'a Layer<'a>,
    c_feature_defn: *const (),
    next_id: int,
    total: int,
}

impl<'a> Iterator<Field<'a>> for FieldIterator<'a> {
    #[inline]
    fn next(&mut self) -> Option<Field<'a>> {
        if self.next_id == self.total {
            return None;
        }
        let field = Field{
            layer: self.layer,
            c_field_defn: unsafe { OGR_FD_GetFieldDefn(
                self.c_feature_defn,
                self.next_id as c_int
            ) }
        };
        self.next_id += 1;
        return Some(field);
    }
}

pub struct Field<'a> {
    layer: &'a Layer<'a>,
    c_field_defn: *const (),
}

impl<'a> Field<'a> {
    pub fn name(&'a self) -> String {
        let rv = unsafe { OGR_Fld_GetNameRef(self.c_field_defn) };
        return _string(rv);
    }
}

pub struct FeatureIterator<'a> {
    layer: &'a Layer<'a>,
}

impl<'a> Iterator<Feature<'a>> for FeatureIterator<'a> {
    #[inline]
    fn next(&mut self) -> Option<Feature<'a>> {
        let c_feature = unsafe { OGR_L_GetNextFeature(self.layer.c_layer) };
        return match c_feature.is_null() {
            true  => None,
            false => Some(Feature{layer: self.layer, c_feature: c_feature}),
        };
    }
}

pub struct Feature<'a> {
    layer: &'a Layer<'a>,
    c_feature: *const (),
}

impl<'a> Feature<'a> {
    pub fn field(&self, name: String) -> Option<FieldValue> {
        return name.with_c_str(|c_name| unsafe {
            let field_id = OGR_F_GetFieldIndex(self.c_feature, c_name);
            if field_id == -1 {
                return None;
            }
            let field_defn = OGR_F_GetFieldDefnRef(self.c_feature, field_id);
            let field_type = OGR_Fld_GetType(field_defn);
            return match field_type {
                OFT_STRING => {
                    let rv = OGR_F_GetFieldAsString(self.c_feature, field_id);
                    return Some(StringValue(_string(rv)));
                },
                OFT_REAL => {
                    let rv = OGR_F_GetFieldAsDouble(self.c_feature, field_id);
                    return Some(RealValue(rv as f64));
                },
                _ => fail!("Unknown field type {}", field_type)
            }
        });
    }

    pub fn wkt(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_wkt: *const c_char = null();
            OGR_G_ExportToWkt(c_geom, &c_wkt);
            let wkt = _string(c_wkt);
            OGRFree(c_wkt as *const ());
            return wkt;
        }
    }

    pub fn json(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_json = OGR_G_ExportToJson(c_geom);
            let json = _string(c_json);
            VSIFree(c_json as *const ());
            return json;
        }
    }
}

#[unsafe_destructor]
impl<'a> Drop for Feature<'a> {
    fn drop(&mut self) {
        unsafe { OGR_F_Destroy(self.c_feature); }
    }
}

pub fn open(path: &Path) -> Option<VectorDataset> {
    register_drivers();
    let filename = path.as_str().unwrap();
    let c_dataset = filename.with_c_str(|c_filename| {
        return unsafe { OGROpen(c_filename, 0, null()) };
    });
    return match c_dataset.is_null() {
        true  => None,
        false => Some(VectorDataset{c_dataset: c_dataset}),
    };
}

pub enum FieldValue {
    StringValue(String),
    RealValue(f64),
}

impl FieldValue {
    pub fn as_string(self) -> String {
        match self { StringValue(rv) => rv, _ => fail!("not a StringValue") }
    }

    pub fn as_real(self) -> f64 {
        match self { RealValue(rv) => rv, _ => fail!("not a RealValue") }
    }
}

#[cfg(test)]
mod test {
    use std::os::getenv;
    use std::path::Path;
    use super::{Feature, FeatureIterator, open};

    fn fixture_path(name: &str) -> Path {
        let envvar = "RUST_GDAL_TEST_FIXTURES";
        let fixtures = match getenv(envvar) {
            Some(p) => Path::new(p),
            None => fail!("Environment variable {} not set", envvar)
        };
        let rv = fixtures.join(name);
        return rv;
    }

    fn assert_almost_eq(a: f64, b: f64) {
        let f: f64 = a / b;
        assert!(f < 1.00001);
        assert!(f > 0.99999);
    }

    #[test]
    fn test_layer_count() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        assert_eq!(ds.layer_count(), 1);
    }

    fn with_features(fixture: &str, f: |FeatureIterator|) {
        let ds = open(&fixture_path(fixture)).unwrap();
        let layer = ds.layer(0).unwrap();
        f(layer.features());
    }

    fn with_first_feature(fixture: &str, f: |Feature|) {
        with_features(fixture, |mut features| f(features.next().unwrap()));
    }

    #[test]
    fn test_iterate_features() {
        with_features("roads.geojson", |mut features| {
            let feature_vec: Vec<Feature> = features.collect();
            assert_eq!(feature_vec.len(), 21);
        });
    }

    #[test]
    fn test_string_field() {
        with_features("roads.geojson", |mut features| {
            let feature = features.next().unwrap();
            assert_eq!(feature.field("highway".to_string())
                              .unwrap()
                              .as_string(),
                       "footway".to_string());
            assert_eq!(
                features.filter(|field| {
                    let highway = field.field("highway".to_string())
                                       .unwrap()
                                       .as_string();
                    highway == "residential".to_string() })
                    .count(),
                2);
        });
    }

    #[test]
    fn test_float_field() {
        with_first_feature("roads.geojson", |feature| {
            assert_almost_eq(
                feature.field("sort_key".to_string())
                       .unwrap()
                       .as_real(),
                -9.0
            );
        });
    }

    #[test]
    fn test_missing_field() {
        with_first_feature("roads.geojson", |feature| {
            assert!(feature.field("no such field".to_string()).is_none());
        });
    }

    #[test]
    fn test_wkt() {
        with_first_feature("roads.geojson", |feature| {
            let wkt = feature.wkt();
            let wkt_ok = format!("{}{}",
                "LINESTRING (26.1019276 44.4302748,",
                "26.1019382 44.4303191,26.1020002 44.4304202)"
                ).to_string();
            assert_eq!(wkt, wkt_ok);
        });
    }

    #[test]
    fn test_json() {
        with_first_feature("roads.geojson", |feature| {
            let json = feature.json();
            let json_ok = format!("{}{}{}{}",
                "{ \"type\": \"LineString\", \"coordinates\": [ ",
                "[ 26.1019276, 44.4302748 ], ",
                "[ 26.1019382, 44.4303191 ], ",
                "[ 26.1020002, 44.4304202 ] ] }"
                ).to_string();
            assert_eq!(json, json_ok);
        });
    }

    #[test]
    fn test_schema() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.layer(0).unwrap();
        let name_list: Vec<String> = layer
            .fields()
            .map(|f| f.name())
            .collect();
        let ok_names = vec!("kind", "sort_key", "is_link", "is_tunnel",
                        "is_bridge", "railway", "highway")
                       .iter().map(|s| s.to_string()).collect();
        assert_eq!(name_list, ok_names);
    }
}
<|endoftext|>


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

use render::glsl;
use gl;

pub fn add_shaders(reg: &mut glsl::Registry) {
    reg.register("lookup_texture",
                 include_str!("shaders/lookup_texture.glsl"));
    reg.register("get_light", include_str!("shaders/get_light.glsl"));

    reg.register("ui_vertex", include_str!("shaders/ui_vertex.glsl"));
    reg.register("ui_frag", include_str!("shaders/ui_frag.glsl"));

    reg.register("chunk_vertex", include_str!("shaders/chunk_vertex.glsl"));
    reg.register("chunk_frag", include_str!("shaders/chunk_frag.glsl"));

    reg.register("trans_vertex", include_str!("shaders/trans_vertex.glsl"));
    reg.register("trans_frag", include_str!("shaders/trans_frag.glsl"));
}

macro_rules! get_shader {
    ($reg:ident, $name:expr) => (
        $reg.get($name)
    );
    ($reg:ident, $name:expr, $def:expr) => (
        $reg.get_define($name, $def)
    )
}

#[macro_export]
macro_rules! init_shader {
    (
        Program $name:ident {
            vert = $vert:expr, $(#$vdef:ident)*
            frag = $frag:expr, $(#$fdef:ident)*
            attribute = {
                $(
                    $field:ident => $glname:expr,
                )*
            },
            uniform = {
                $(
                    $ufield:ident => $uglname:expr,
                )*
            },
        }
    ) => (
        #[allow(dead_code)]
        struct $name {
            program: gl::Program,
            $(
                $field: gl::Attribute,
            )+
            $(
                $ufield: gl::Uniform,
            )+
        }

        impl $name {
            pub fn new(reg: &glsl::Registry) -> $name {
                let v = get_shader!(reg, $vert $(,stringify!($vdef))*);
                let f = get_shader!(reg, $frag $(,stringify!($fdef))*);
                let shader = shaders::create_program(&v, &f);
                $name {
                    $(
                        $field: shader.attribute_location($glname),
                    )+
                    $(
                        $ufield: shader.uniform_location($uglname),
                    )+
                    program: shader,
                }
            }
        }
    )
}

pub fn create_program(vertex: &str, fragment: &str) -> gl::Program {
    let program = gl::Program::new();

    let v = gl::Shader::new(gl::VERTEX_SHADER);
    v.set_source(vertex);
    v.compile();

    if v.get_parameter(gl::COMPILE_STATUS) == 0 {
        println!("Src: {}", vertex);
        panic!("Shader error: {}", v.get_info_log());
    } else {
        let log = v.get_info_log();
        if !log.is_empty() {
            println!("{}", log);
        }
    }

    let f = gl::Shader::new(gl::FRAGMENT_SHADER);
    f.set_source(fragment);
    f.compile();

    if f.get_parameter(gl::COMPILE_STATUS) == 0 {
        println!("Src: {}", fragment);
        panic!("Shader error: {}", f.get_info_log());
    } else {
        let log = f.get_info_log();
        if !log.is_empty() {
            println!("{}", log);
        }
    }

    program.attach_shader(v);
    program.attach_shader(f);
    program.link();
    program.use_program();
    program
}
<commit_msg>Fix empty line spam on startup<commit_after>// Copyright 2016 Matthew Collins
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use render::glsl;
use gl;

pub fn add_shaders(reg: &mut glsl::Registry) {
    reg.register("lookup_texture",
                 include_str!("shaders/lookup_texture.glsl"));
    reg.register("get_light", include_str!("shaders/get_light.glsl"));

    reg.register("ui_vertex", include_str!("shaders/ui_vertex.glsl"));
    reg.register("ui_frag", include_str!("shaders/ui_frag.glsl"));

    reg.register("chunk_vertex", include_str!("shaders/chunk_vertex.glsl"));
    reg.register("chunk_frag", include_str!("shaders/chunk_frag.glsl"));

    reg.register("trans_vertex", include_str!("shaders/trans_vertex.glsl"));
    reg.register("trans_frag", include_str!("shaders/trans_frag.glsl"));
}

macro_rules! get_shader {
    ($reg:ident, $name:expr) => (
        $reg.get($name)
    );
    ($reg:ident, $name:expr, $def:expr) => (
        $reg.get_define($name, $def)
    )
}

#[macro_export]
macro_rules! init_shader {
    (
        Program $name:ident {
            vert = $vert:expr, $(#$vdef:ident)*
            frag = $frag:expr, $(#$fdef:ident)*
            attribute = {
                $(
                    $field:ident => $glname:expr,
                )*
            },
            uniform = {
                $(
                    $ufield:ident => $uglname:expr,
                )*
            },
        }
    ) => (
        #[allow(dead_code)]
        struct $name {
            program: gl::Program,
            $(
                $field: gl::Attribute,
            )+
            $(
                $ufield: gl::Uniform,
            )+
        }

        impl $name {
            pub fn new(reg: &glsl::Registry) -> $name {
                let v = get_shader!(reg, $vert $(,stringify!($vdef))*);
                let f = get_shader!(reg, $frag $(,stringify!($fdef))*);
                let shader = shaders::create_program(&v, &f);
                $name {
                    $(
                        $field: shader.attribute_location($glname),
                    )+
                    $(
                        $ufield: shader.uniform_location($uglname),
                    )+
                    program: shader,
                }
            }
        }
    )
}

pub fn create_program(vertex: &str, fragment: &str) -> gl::Program {
    let program = gl::Program::new();

    let v = gl::Shader::new(gl::VERTEX_SHADER);
    v.set_source(vertex);
    v.compile();

    if v.get_parameter(gl::COMPILE_STATUS) == 0 {
        println!("Src: {}", vertex);
        panic!("Shader error: {}", v.get_info_log());
    } else {
        let log = v.get_info_log();
        let log = log.trim().trim_matches('\u{0}');
        if !log.is_empty() {
            println!("{}", log);
        }
    }

    let f = gl::Shader::new(gl::FRAGMENT_SHADER);
    f.set_source(fragment);
    f.compile();

    if f.get_parameter(gl::COMPILE_STATUS) == 0 {
        println!("Src: {}", fragment);
        panic!("Shader error: {}", f.get_info_log());
    } else {
        let log = f.get_info_log();
        let log = log.trim().trim_matches('\u{0}');
        if !log.is_empty() {
            println!("{}", log);
        }
    }

    program.attach_shader(v);
    program.attach_shader(f);
    program.link();
    program.use_program();
    program
}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate decodeopts;
extern crate serialize;

use getopts::{reqopt,optopt,optflag,getopts,OptGroup};
use std::os;
use serialize::Decodable;
use std::task;
use std::any::AnyRefExt;
use decodeopts::{Error, UnimplementedDecoder,MissingField,ExpectedType};

#[deriving(Decodable)]
enum Color {
  red,
  blue
}

#[deriving(Decodable)]
pub struct TestStruct1  {
  data_int: u8,
  data_str: ~str,
  color: Color,
  maybe: Option<int>
}

fn do_work(inp: &str, out: Option<~str>) {
    println!("{}", inp);
    match out {
        Some(x) => println!("{}", x),
        None => println!("No Output"),
    }
}

fn print_usage(program: &str, _opts: &[OptGroup]) {
    println!("Usage: {} [options]", program);
    println!("-o\t\tOutput");
    println!("-d --data_int\tNumber");
    println!("-h --help\tUsage");
}

fn main() {
  let args = os::args();

  let program = args[0].clone();

  let opts = ~[
    optopt("o", "", "set output file name", "NAME"),
    reqopt("d", "data_int", "number", "NB"),
    reqopt("s", "data_str", "str", "NB"),
    reqopt("c", "color", "scolored", ""),
    optopt("m", "maybe", "maybe int", ""),
    optflag("h", "help", "print this help menu")
  ];
  let matches = match getopts(args.tail(), opts) {
    Ok(m) => { m }
    Err(f) => { fail!(f.to_err_msg()) }
  };

  if matches.opt_present("h") {
    print_usage(program, opts);
    return;
  }

  let result = task::try(proc() {
    let mut decoder = decodeopts::Decoder::new(matches);
    let decoded: TestStruct1 = Decodable::decode(&mut decoder);

    println!("got data: s -> {} n -> {}", decoded.data_str, decoded.data_int);
    match decoded.color {
      red  => println!("red"),
      blue => println!("blue")
    }

    match decoded.maybe {
      None    => println!("maybe is none"),
      Some(i) => println!("maybe is {}", i)
    }
  });

  match result {
    Ok(a) => println!("everything is ok"),
    Err(e)      => {
      let err = e.as_ref::<Error>().unwrap();
      match err.e {
        UnimplementedDecoder => println!("this function is not implemented"),
        MissingField(ref s)  => println!("the required field '{}' is not present", s),
        ExpectedType(ref field, ref expected, ref value) => {
          println!("Expected type '{}' for field '{}' but got value '{}'", expected, field, value)
        }
      }
    }
  }
}
<commit_msg>Simplify the example<commit_after>extern crate getopts;
extern crate decodeopts;
extern crate serialize;

use getopts::{reqopt,optopt,optflag,getopts,OptGroup};
use std::os;
use serialize::Decodable;
use decodeopts::{DecoderResult,UnimplementedDecoder,MissingField,ExpectedType};

#[deriving(Decodable)]
enum Color {
  red,
  blue
}

#[deriving(Decodable)]
pub struct TestStruct1  {
  data_int: u8,
  data_str: ~str,
  color: Color,
  maybe: Option<int>
}

fn do_work(inp: &str, out: Option<~str>) {
    println!("{}", inp);
    match out {
        Some(x) => println!("{}", x),
        None => println!("No Output"),
    }
}

fn print_usage(program: &str, _opts: &[OptGroup]) {
    println!("Usage: {} [options]", program);
    println!("-o\t\tOutput");
    println!("-d --data_int\tNumber");
    println!("-h --help\tUsage");
}

fn main() {
  let args = os::args();

  let program = args[0].clone();

  let opts = ~[
    optopt("o", "", "set output file name", "NAME"),
    reqopt("d", "data_int", "number", "NB"),
    reqopt("s", "data_str", "str", "NB"),
    reqopt("c", "color", "scolored", ""),
    optopt("m", "maybe", "maybe int", ""),
    optflag("h", "help", "print this help menu")
  ];
  let matches = match getopts(args.tail(), opts) {
    Ok(m) => { m }
    Err(f) => { fail!(f.to_err_msg()) }
  };

  if matches.opt_present("h") {
    print_usage(program, opts);
    return;
  }

  let result: decodeopts::DecoderResult<TestStruct1> = decodeopts::decode(matches);

  match result {
    Ok(decoded) => {
      println!("got data: s -> {} n -> {}", decoded.data_str, decoded.data_int);
      match decoded.color {
        red  => println!("red"),
        blue => println!("blue")
      }

      match decoded.maybe {
        None    => println!("maybe is none"),
        Some(i) => println!("maybe is {}", i)
      }
    },
    Err(UnimplementedDecoder) => println!("this function is not implemented"),
    Err(MissingField(ref s))  => println!("the required field '{}' is not present", s),
    Err(ExpectedType(ref field, ref expected, ref value)) => {
      println!("Expected type '{}' for field '{}' but got value '{}'", expected, field, value)
    }
  }
}
<|endoftext|>


<commit_before>// Copyright (C) 2018, Cloudflare, Inc.
// Copyright (C) 2018, Alessandro Ghedini
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#[macro_use]
extern crate log;

use std::net;

use std::collections::HashMap;

use ring::rand::*;

const LOCAL_CONN_ID_LEN: usize = 16;

const MAX_DATAGRAM_SIZE: usize = 1350;

const USAGE: &str = "Usage:
  server [options]
  server -h | --help

Options:
  --listen <addr>   Listen on the given IP:port [default: 127.0.0.1:4433]
  --cert <file>     TLS certificate path [default: examples/cert.crt]
  --key <file>      TLS certificate key path [default: examples/cert.key]
  --root <dir>      Root directory [default: examples/root/]
  --name <str>      Name of the server [default: quic.tech]
  --no-retry        Disable stateless retry.
  -h --help         Show this screen.
";

type ConnMap = HashMap<Vec<u8>, (net::SocketAddr, Box<quiche::Connection>)>;

fn main() -> Result<(), Box<std::error::Error>> {
    let mut buf = [0; 65535];
    let mut out = [0; MAX_DATAGRAM_SIZE];

    env_logger::init();

    let args = docopt::Docopt::new(USAGE)
        .and_then(|dopt| dopt.parse())
        .unwrap_or_else(|e| e.exit());

    let socket = net::UdpSocket::bind(args.get_str("--listen"))?;

    let poll = mio::Poll::new()?;
    let mut events = mio::Events::with_capacity(1024);

    let socket = mio::net::UdpSocket::from_socket(socket)?;
    poll.register(
        &socket,
        mio::Token(0),
        mio::Ready::readable(),
        mio::PollOpt::edge(),
    )?;

    let mut connections = ConnMap::new();

    let mut config = quiche::Config::new(quiche::VERSION_DRAFT18)?;

    config.load_cert_chain_from_pem_file(args.get_str("--cert"))?;
    config.load_priv_key_from_pem_file(args.get_str("--key"))?;

    config.set_application_protos(b"\x05hq-18\x08http/0.9")?;

    config.set_idle_timeout(30);
    config.set_max_packet_size(MAX_DATAGRAM_SIZE as u64);
    config.set_initial_max_data(10_000_000);
    config.set_initial_max_stream_data_bidi_local(1_000_000);
    config.set_initial_max_stream_data_bidi_remote(1_000_000);
    config.set_initial_max_stream_data_uni(1_000_000);
    config.set_initial_max_streams_bidi(100);
    config.set_initial_max_streams_uni(5);
    config.set_disable_migration(true);

    if std::env::var_os("SSLKEYLOGFILE").is_some() {
        config.log_keys();
    }

    loop {
        // TODO: use event loop that properly supports timers
        let timeout = connections.values().filter_map(|(_, c)| c.timeout()).min();

        poll.poll(&mut events, timeout)?;

        'read: loop {
            if events.is_empty() {
                debug!("timed out");

                connections.values_mut().for_each(|(_, c)| c.on_timeout());

                break 'read;
            }

            let (len, src) = match socket.recv_from(&mut buf) {
                Ok(v) => v,

                Err(e) => {
                    if e.kind() == std::io::ErrorKind::WouldBlock {
                        debug!("recv() would block");
                        break 'read;
                    }

                    panic!("recv() failed: {:?}", e);
                },
            };

            debug!("got {} bytes", len);

            let pkt_buf = &mut buf[..len];

            let hdr = match quiche::Header::from_slice(pkt_buf, LOCAL_CONN_ID_LEN)
            {
                Ok(v) => v,

                Err(e) => {
                    error!("Parsing packet header failed: {:?}", e);
                    continue;
                },
            };

            trace!("got packet {:?}", hdr);

            if hdr.ty == quiche::Type::VersionNegotiation {
                error!("Version negotiation invalid on the server");
                continue;
            }

            let (_, conn) = if !connections.contains_key(&hdr.dcid) {
                if hdr.ty != quiche::Type::Initial {
                    error!("Packet is not Initial");
                    continue;
                }

                if hdr.version != quiche::VERSION_DRAFT18 {
                    warn!("Doing version negotiation");

                    let len = quiche::negotiate_version(
                        &hdr.scid, &hdr.dcid, &mut out,
                    )?;

                    let out = &out[..len];

                    socket.send_to(out, &src)?;
                    continue;
                }

                let mut scid = [0; LOCAL_CONN_ID_LEN];
                SystemRandom::new().fill(&mut scid[..])?;

                let mut odcid = None;

                if !args.get_bool("--no-retry") {
                    // Token is always present in Initial packets.
                    let token = hdr.token.as_ref().unwrap();

                    if token.is_empty() {
                        warn!("Doing stateless retry");

                        let new_token = mint_token(&hdr, &src);

                        let len = quiche::retry(
                            &hdr.scid, &hdr.dcid, &scid, &new_token, &mut out,
                        )?;

                        let out = &out[..len];

                        socket.send_to(out, &src)?;
                        continue;
                    }

                    odcid = validate_token(&src, token);

                    if odcid == None {
                        error!("Invalid address validation token");
                        continue;
                    }

                    scid.copy_from_slice(&hdr.dcid);
                }

                debug!(
                    "New connection: dcid={} scid={}",
                    hex_dump(&hdr.dcid),
                    hex_dump(&scid)
                );

                let conn = quiche::accept(&scid, odcid, &mut config)?;

                connections.insert(scid.to_vec(), (src, conn));

                connections.get_mut(&scid[..]).unwrap()
            } else {
                connections.get_mut(&hdr.dcid).unwrap()
            };

            // Process potentially coalesced packets.
            let read = match conn.recv(pkt_buf) {
                Ok(v) => v,

                Err(quiche::Error::Done) => {
                    debug!("{} done reading", conn.trace_id());
                    break;
                },

                Err(e) => {
                    error!("{} recv failed: {:?}", conn.trace_id(), e);
                    conn.close(false, e.to_wire(), b"fail")?;
                    break 'read;
                },
            };

            debug!("{} processed {} bytes", conn.trace_id(), read);

            let streams: Vec<u64> = conn.readable().collect();
            for s in streams {
                while let Ok((read, fin)) = conn.stream_recv(s, &mut buf) {
                    debug!("{} received {} bytes", conn.trace_id(), read);

                    let stream_buf = &buf[..read];

                    debug!(
                        "{} stream {} has {} bytes (fin? {})",
                        conn.trace_id(),
                        s,
                        stream_buf.len(),
                        fin
                    );

                    handle_stream(conn, s, stream_buf, args.get_str("--root"));
                }
            }
        }

        for (peer, conn) in connections.values_mut() {
            loop {
                let write = match conn.send(&mut out) {
                    Ok(v) => v,

                    Err(quiche::Error::Done) => {
                        debug!("{} done writing", conn.trace_id());
                        break;
                    },

                    Err(e) => {
                        error!("{} send failed: {:?}", conn.trace_id(), e);
                        conn.close(false, e.to_wire(), b"fail")?;
                        break;
                    },
                };

                // TODO: coalesce packets.
                socket.send_to(&out[..write], &peer)?;

                debug!("{} written {} bytes", conn.trace_id(), write);
            }
        }

        // Garbage collect closed connections.
        connections.retain(|_, (_, ref mut c)| {
            debug!("Collecting garbage");

            if c.is_closed() {
                info!("{} connection collected {:?}", c.trace_id(), c.stats());
            }

            !c.is_closed()
        });
    }
}

fn handle_stream(
    conn: &mut quiche::Connection, stream: u64, buf: &[u8], root: &str,
) {
    if buf.len() > 4 && &buf[..4] == b"GET " {
        let uri = &buf[4..buf.len()];
        let uri = String::from_utf8(uri.to_vec()).unwrap();
        let uri = String::from(uri.lines().next().unwrap());
        let uri = std::path::Path::new(&uri);
        let mut path = std::path::PathBuf::from(root);

        for c in uri.components() {
            if let std::path::Component::Normal(v) = c {
                path.push(v)
            }
        }

        info!(
            "{} got GET request for {:?} on stream {}",
            conn.trace_id(),
            path,
            stream
        );

        let data = std::fs::read(path.as_path())
            .unwrap_or_else(|_| b"Not Found!\r\n".to_vec());

        info!(
            "{} sending response of size {} on stream {}",
            conn.trace_id(),
            data.len(),
            stream
        );

        if let Err(e) = conn.stream_send(stream, &data, true) {
            error!("{} stream send failed {:?}", conn.trace_id(), e);
        }
    }
}

fn mint_token(hdr: &quiche::Header, src: &net::SocketAddr) -> Vec<u8> {
    let mut token = Vec::new();

    token.extend_from_slice(b"quiche");

    let addr = match src.ip() {
        std::net::IpAddr::V4(a) => a.octets().to_vec(),
        std::net::IpAddr::V6(a) => a.octets().to_vec(),
    };

    token.extend_from_slice(&addr);
    token.extend_from_slice(&hdr.dcid);

    token
}

fn validate_token<'a>(
    src: &net::SocketAddr, token: &'a [u8],
) -> Option<&'a [u8]> {
    if token.len() < 6 {
        return None;
    }

    if &token[..6] != b"quiche" {
        return None;
    }

    let token = &token[6..];

    let addr = match src.ip() {
        std::net::IpAddr::V4(a) => a.octets().to_vec(),
        std::net::IpAddr::V6(a) => a.octets().to_vec(),
    };

    if token.len() < addr.len() || &token[..addr.len()] != addr.as_slice() {
        return None;
    }

    let token = &token[addr.len()..];

    Some(&token[..])
}

fn hex_dump(buf: &[u8]) -> String {
    let vec: Vec<String> = buf.iter().map(|b| format!("{:02x}", b)).collect();

    vec.join("")
}
<commit_msg>server: only read stream data when the connection is established<commit_after>// Copyright (C) 2018, Cloudflare, Inc.
// Copyright (C) 2018, Alessandro Ghedini
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#[macro_use]
extern crate log;

use std::net;

use std::collections::HashMap;

use ring::rand::*;

const LOCAL_CONN_ID_LEN: usize = 16;

const MAX_DATAGRAM_SIZE: usize = 1350;

const USAGE: &str = "Usage:
  server [options]
  server -h | --help

Options:
  --listen <addr>   Listen on the given IP:port [default: 127.0.0.1:4433]
  --cert <file>     TLS certificate path [default: examples/cert.crt]
  --key <file>      TLS certificate key path [default: examples/cert.key]
  --root <dir>      Root directory [default: examples/root/]
  --name <str>      Name of the server [default: quic.tech]
  --no-retry        Disable stateless retry.
  -h --help         Show this screen.
";

type ConnMap = HashMap<Vec<u8>, (net::SocketAddr, Box<quiche::Connection>)>;

fn main() -> Result<(), Box<std::error::Error>> {
    let mut buf = [0; 65535];
    let mut out = [0; MAX_DATAGRAM_SIZE];

    env_logger::init();

    let args = docopt::Docopt::new(USAGE)
        .and_then(|dopt| dopt.parse())
        .unwrap_or_else(|e| e.exit());

    let socket = net::UdpSocket::bind(args.get_str("--listen"))?;

    let poll = mio::Poll::new()?;
    let mut events = mio::Events::with_capacity(1024);

    let socket = mio::net::UdpSocket::from_socket(socket)?;
    poll.register(
        &socket,
        mio::Token(0),
        mio::Ready::readable(),
        mio::PollOpt::edge(),
    )?;

    let mut connections = ConnMap::new();

    let mut config = quiche::Config::new(quiche::VERSION_DRAFT18)?;

    config.load_cert_chain_from_pem_file(args.get_str("--cert"))?;
    config.load_priv_key_from_pem_file(args.get_str("--key"))?;

    config.set_application_protos(b"\x05hq-18\x08http/0.9")?;

    config.set_idle_timeout(30);
    config.set_max_packet_size(MAX_DATAGRAM_SIZE as u64);
    config.set_initial_max_data(10_000_000);
    config.set_initial_max_stream_data_bidi_local(1_000_000);
    config.set_initial_max_stream_data_bidi_remote(1_000_000);
    config.set_initial_max_stream_data_uni(1_000_000);
    config.set_initial_max_streams_bidi(100);
    config.set_initial_max_streams_uni(5);
    config.set_disable_migration(true);

    if std::env::var_os("SSLKEYLOGFILE").is_some() {
        config.log_keys();
    }

    loop {
        // TODO: use event loop that properly supports timers
        let timeout = connections.values().filter_map(|(_, c)| c.timeout()).min();

        poll.poll(&mut events, timeout)?;

        'read: loop {
            if events.is_empty() {
                debug!("timed out");

                connections.values_mut().for_each(|(_, c)| c.on_timeout());

                break 'read;
            }

            let (len, src) = match socket.recv_from(&mut buf) {
                Ok(v) => v,

                Err(e) => {
                    if e.kind() == std::io::ErrorKind::WouldBlock {
                        debug!("recv() would block");
                        break 'read;
                    }

                    panic!("recv() failed: {:?}", e);
                },
            };

            debug!("got {} bytes", len);

            let pkt_buf = &mut buf[..len];

            let hdr = match quiche::Header::from_slice(pkt_buf, LOCAL_CONN_ID_LEN)
            {
                Ok(v) => v,

                Err(e) => {
                    error!("Parsing packet header failed: {:?}", e);
                    continue;
                },
            };

            trace!("got packet {:?}", hdr);

            if hdr.ty == quiche::Type::VersionNegotiation {
                error!("Version negotiation invalid on the server");
                continue;
            }

            let (_, conn) = if !connections.contains_key(&hdr.dcid) {
                if hdr.ty != quiche::Type::Initial {
                    error!("Packet is not Initial");
                    continue;
                }

                if hdr.version != quiche::VERSION_DRAFT18 {
                    warn!("Doing version negotiation");

                    let len = quiche::negotiate_version(
                        &hdr.scid, &hdr.dcid, &mut out,
                    )?;

                    let out = &out[..len];

                    socket.send_to(out, &src)?;
                    continue;
                }

                let mut scid = [0; LOCAL_CONN_ID_LEN];
                SystemRandom::new().fill(&mut scid[..])?;

                let mut odcid = None;

                if !args.get_bool("--no-retry") {
                    // Token is always present in Initial packets.
                    let token = hdr.token.as_ref().unwrap();

                    if token.is_empty() {
                        warn!("Doing stateless retry");

                        let new_token = mint_token(&hdr, &src);

                        let len = quiche::retry(
                            &hdr.scid, &hdr.dcid, &scid, &new_token, &mut out,
                        )?;

                        let out = &out[..len];

                        socket.send_to(out, &src)?;
                        continue;
                    }

                    odcid = validate_token(&src, token);

                    if odcid == None {
                        error!("Invalid address validation token");
                        continue;
                    }

                    scid.copy_from_slice(&hdr.dcid);
                }

                debug!(
                    "New connection: dcid={} scid={}",
                    hex_dump(&hdr.dcid),
                    hex_dump(&scid)
                );

                let conn = quiche::accept(&scid, odcid, &mut config)?;

                connections.insert(scid.to_vec(), (src, conn));

                connections.get_mut(&scid[..]).unwrap()
            } else {
                connections.get_mut(&hdr.dcid).unwrap()
            };

            // Process potentially coalesced packets.
            let read = match conn.recv(pkt_buf) {
                Ok(v) => v,

                Err(quiche::Error::Done) => {
                    debug!("{} done reading", conn.trace_id());
                    break;
                },

                Err(e) => {
                    error!("{} recv failed: {:?}", conn.trace_id(), e);
                    conn.close(false, e.to_wire(), b"fail")?;
                    break 'read;
                },
            };

            debug!("{} processed {} bytes", conn.trace_id(), read);

            if conn.is_established() {
                let streams: Vec<u64> = conn.readable().collect();
                for s in streams {
                    while let Ok((read, fin)) = conn.stream_recv(s, &mut buf) {
                        debug!("{} received {} bytes", conn.trace_id(), read);

                        let stream_buf = &buf[..read];

                        debug!(
                            "{} stream {} has {} bytes (fin? {})",
                            conn.trace_id(),
                            s,
                            stream_buf.len(),
                            fin
                        );

                        handle_stream(
                            conn,
                            s,
                            stream_buf,
                            args.get_str("--root"),
                        );
                    }
                }
            }
        }

        for (peer, conn) in connections.values_mut() {
            loop {
                let write = match conn.send(&mut out) {
                    Ok(v) => v,

                    Err(quiche::Error::Done) => {
                        debug!("{} done writing", conn.trace_id());
                        break;
                    },

                    Err(e) => {
                        error!("{} send failed: {:?}", conn.trace_id(), e);
                        conn.close(false, e.to_wire(), b"fail")?;
                        break;
                    },
                };

                // TODO: coalesce packets.
                socket.send_to(&out[..write], &peer)?;

                debug!("{} written {} bytes", conn.trace_id(), write);
            }
        }

        // Garbage collect closed connections.
        connections.retain(|_, (_, ref mut c)| {
            debug!("Collecting garbage");

            if c.is_closed() {
                info!("{} connection collected {:?}", c.trace_id(), c.stats());
            }

            !c.is_closed()
        });
    }
}

fn handle_stream(
    conn: &mut quiche::Connection, stream: u64, buf: &[u8], root: &str,
) {
    if buf.len() > 4 && &buf[..4] == b"GET " {
        let uri = &buf[4..buf.len()];
        let uri = String::from_utf8(uri.to_vec()).unwrap();
        let uri = String::from(uri.lines().next().unwrap());
        let uri = std::path::Path::new(&uri);
        let mut path = std::path::PathBuf::from(root);

        for c in uri.components() {
            if let std::path::Component::Normal(v) = c {
                path.push(v)
            }
        }

        info!(
            "{} got GET request for {:?} on stream {}",
            conn.trace_id(),
            path,
            stream
        );

        let data = std::fs::read(path.as_path())
            .unwrap_or_else(|_| b"Not Found!\r\n".to_vec());

        info!(
            "{} sending response of size {} on stream {}",
            conn.trace_id(),
            data.len(),
            stream
        );

        if let Err(e) = conn.stream_send(stream, &data, true) {
            error!("{} stream send failed {:?}", conn.trace_id(), e);
        }
    }
}

fn mint_token(hdr: &quiche::Header, src: &net::SocketAddr) -> Vec<u8> {
    let mut token = Vec::new();

    token.extend_from_slice(b"quiche");

    let addr = match src.ip() {
        std::net::IpAddr::V4(a) => a.octets().to_vec(),
        std::net::IpAddr::V6(a) => a.octets().to_vec(),
    };

    token.extend_from_slice(&addr);
    token.extend_from_slice(&hdr.dcid);

    token
}

fn validate_token<'a>(
    src: &net::SocketAddr, token: &'a [u8],
) -> Option<&'a [u8]> {
    if token.len() < 6 {
        return None;
    }

    if &token[..6] != b"quiche" {
        return None;
    }

    let token = &token[6..];

    let addr = match src.ip() {
        std::net::IpAddr::V4(a) => a.octets().to_vec(),
        std::net::IpAddr::V6(a) => a.octets().to_vec(),
    };

    if token.len() < addr.len() || &token[..addr.len()] != addr.as_slice() {
        return None;
    }

    let token = &token[addr.len()..];

    Some(&token[..])
}

fn hex_dump(buf: &[u8]) -> String {
    let vec: Vec<String> = buf.iter().map(|b| format!("{:02x}", b)).collect();

    vec.join("")
}
<|endoftext|>


<commit_before>use rust_rocket::{Event, Rocket};
use std::time::Duration;

fn main() -> Result<(), rust_rocket::Error> {
    let mut rocket = Rocket::new()?;
    rocket.get_track_mut("test")?;
    rocket.get_track_mut("test2")?;
    rocket.get_track_mut("a:test2")?;

    let mut current_row = 0;
    loop {
        if let Some(event) = rocket.poll_events()? {
            match event {
                Event::SetRow(row) => {
                    println!("SetRow (row: {:?})", row);
                    current_row = row;
                }
                Event::Pause(_) => {
                    let track1 = rocket.get_track("test").unwrap();
                    println!(
                        "Pause (value: {:?}) (row: {:?})",
                        track1.get_value(current_row as f32),
                        current_row
                    );
                }
                _ => (),
            }
            println!("{:?}", event);
        }
        std::thread::sleep(Duration::from_millis(16));
    }
}
<commit_msg>Improve example code<commit_after>use rust_rocket::{Event, Rocket};
use std::time::Duration;

fn main() -> Result<(), rust_rocket::Error> {
    let mut rocket = Rocket::new()?;
    rocket.get_track_mut("test")?;
    rocket.get_track_mut("test2")?;
    rocket.get_track_mut("a:test2")?;

    let mut current_row = 0;
    let mut paused = true;

    loop {
        if let Some(event) = rocket.poll_events()? {
            match event {
                Event::SetRow(row) => {
                    println!("SetRow (row: {:?})", row);
                    current_row = row;
                }
                Event::Pause(state) => {
                    paused = state;

                    let track1 = rocket.get_track("test").unwrap();
                    println!(
                        "Pause (value: {:?}) (row: {:?})",
                        track1.get_value(current_row as f32),
                        current_row
                    );
                }
                Event::SaveTracks => {
                    println!("Saving tracks");
                    rocket.save_tracks("tracks.bin")?;
                }
            }
            println!("{:?}", event);
        }

        if !paused {
            current_row += 1;
            rocket.set_row(current_row)?;
        }

        std::thread::sleep(Duration::from_millis(32));
    }
}
<|endoftext|>