<commit_before>#![allow(non_camel_case_types)]
extern crate libc;
extern crate glib;

use libc::{c_uint, c_char, c_int, c_ulong, c_long};
use glib::ffi::{GError, GType, GList, gboolean, gsize, gpointer, GHashTable};

//glib stuff not provided by glib-rs
pub type gchar = c_char;
pub type gint = c_int;
pub type guint = c_uint;
pub type guint64 = c_ulong;
pub type gssize = c_long;
#[repr(C)] pub struct GCancellable;

//libsecret

#[repr(C)] pub struct SecretServiceFFI;
#[repr(C)] pub struct SecretSchemaFFI;
#[repr(C)] pub struct SecretCollectionFFI;
#[repr(C)] pub struct SecretItemFFI;
#[repr(C)] pub struct SecretValueFFI;

#[link(name="secret-1")]
extern "C" {
    //=========================================================================
    // SecretService
    //=========================================================================
    pub fn secret_service_get_sync              (flags: c_int, cancellable: *mut GCancellable, error: *mut *mut GError) -> *mut SecretServiceFFI;
    pub fn secret_service_disconnect            ();
    pub fn secret_service_open_sync             (service_gtype: GType, service_bus_name: *const gchar, flags: c_int, cancellable: *mut GCancellable, error: *mut *mut GError) -> *mut SecretServiceFFI;
    pub fn secret_service_get_collections       (secret_service: *mut SecretServiceFFI) -> *mut GList;
    pub fn secret_service_get_flags             (secret_service: *mut SecretServiceFFI) -> c_int;
    pub fn secret_service_get_session_algorithms(secret_service: *mut SecretServiceFFI) -> *const gchar;
    pub fn secret_service_ensure_session_sync   (secret_service: *mut SecretServiceFFI, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_service_load_collections_sync (secret_service: *mut SecretServiceFFI, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_service_search_sync           (secret_service: *mut SecretServiceFFI, secret_schema: *const SecretSchemaFFI, attributes: *mut GHashTable, flags: c_int, cancellable: *mut GCancellable, error: *mut *mut GError) -> *mut GList;
    pub fn secret_service_lock_sync             (secret_service: *mut SecretServiceFFI, objects: *mut GList, cancellable: *mut GCancellable, locked: *mut *mut GList, error: *mut *mut GError);
    pub fn secret_service_unlock_sync           (secret_service: *mut SecretServiceFFI, objects: *mut GList, cancellable: *mut GCancellable, unlocked: *mut *mut GList, error: *mut *mut GError) -> gint;
    pub fn secret_service_store_sync            (secret_service: *mut SecretServiceFFI, schema: *const SecretSchemaFFI, attributes: *mut GHashTable, collection: *const gchar, label: *const gchar, value: *mut SecretValueFFI, cancellable: *mut GCancellable, error: *mut *mut GError);
    pub fn secret_service_lookup_sync           (secret_service: *mut SecretServiceFFI, schema: *const SecretSchemaFFI, attributes: *mut GHashTable, cancellable: *mut GCancellable, error: *mut *mut GError) -> *mut SecretValueFFI;
    pub fn secret_service_clear_sync            (secret_service: *mut SecretServiceFFI, schema: *const SecretSchemaFFI, attributes: *mut GHashTable, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
//  pub fn secret_service_prompt_sync           ();
    pub fn secret_service_set_alias_sync        (secret_service: *mut SecretServiceFFI, alias: *const gchar, collection: *mut SecretCollectionFFI, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_service_get_collection_gtype  (secret_service: *mut SecretServiceFFI) -> GType;
    pub fn secret_service_get_item_gtype        (secret_service: *mut SecretServiceFFI) -> GType;

    //=========================================================================
    // SecretCollection
    //=========================================================================
    pub fn secret_collection_for_alias_sync (secret_service: *mut SecretServiceFFI, alias: *const gchar, flags: c_int, cancellable: *mut GCancellable, error: *mut *mut GError) -> *mut SecretCollectionFFI;
    pub fn secret_collection_load_items_sync(secret_collection: *mut SecretCollectionFFI, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_collection_create_sync    (secret_service: *mut SecretServiceFFI, label: *const gchar, alias: *const gchar, flags: c_int, cancellable: *mut GCancellable, error: *mut *mut GError) -> *mut SecretCollectionFFI;
    pub fn secret_collection_search_sync    (secret_collection: *mut SecretCollectionFFI, schema: *const SecretSchemaFFI, atrributes: *mut GHashTable, flags: c_int, cancellable: *mut GCancellable, error: *mut *mut GError) -> *mut GList;
    pub fn secret_collection_delete_sync    (secret_collection: *mut SecretCollectionFFI, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_collection_get_created    (secret_collection: *mut SecretCollectionFFI) -> guint64;
    pub fn secret_collection_get_service    (secret_collection: *mut SecretCollectionFFI) -> *mut SecretServiceFFI;
    pub fn secret_collection_get_flags      (secret_collection: *mut SecretCollectionFFI) -> c_int;
    pub fn secret_collection_get_items      (secret_collection: *mut SecretCollectionFFI) -> *mut GList;
    pub fn secret_collection_get_label      (secret_collection: *mut SecretCollectionFFI) -> *mut gchar;
    pub fn secret_collection_set_label_sync (secret_collection: *mut SecretCollectionFFI, label: *const gchar, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_collection_get_locked     (secret_collection: *mut SecretCollectionFFI) -> gboolean;
    pub fn secret_collection_get_modified   (secret_collection: *mut SecretCollectionFFI) -> guint64;
    pub fn secret_collection_refresh        (secret_collection: *mut SecretCollectionFFI);

    //=========================================================================
    // SecretItem
    //=========================================================================
    pub fn secret_item_create_sync          (secret_collection: *mut SecretCollectionFFI, schema: *const SecretSchemaFFI, attributes: *mut GHashTable, label: *const gchar, value: *mut SecretValueFFI, flags: c_int, cancellable: *mut GCancellable, error: *mut *mut GError) -> *mut SecretItemFFI;
    pub fn secret_item_delete_sync          (secret_item: *mut SecretItemFFI, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_item_get_schema_name      (secret_item: *mut SecretItemFFI) -> *mut gchar;
    pub fn secret_item_get_attributes       (secret_item: *mut SecretItemFFI) -> *mut GHashTable;
    pub fn secret_item_set_attributes_sync  (secret_item: *mut SecretItemFFI, schema: *const SecretSchemaFFI, attributes: *mut GHashTable, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_item_get_created          (secret_item: *mut SecretItemFFI) -> guint64;
    pub fn secret_item_get_label            (secret_item: *mut SecretItemFFI) -> *mut gchar;
    pub fn secret_item_set_label_sync       (secret_item: *mut SecretItemFFI, label: *const gchar, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_item_get_flags            (secret_item: *mut SecretItemFFI) -> c_int;
    pub fn secret_item_get_locked           (secret_item: *mut SecretItemFFI) -> gboolean;
    pub fn secret_item_get_modified         (secret_item: *mut SecretItemFFI) -> guint64;
    pub fn secret_item_get_service          (secret_item: *mut SecretItemFFI) -> *mut SecretServiceFFI;
    pub fn secret_item_get_secret           (secret_item: *mut SecretItemFFI) -> *mut SecretValueFFI;
    pub fn secret_item_load_secret_sync     (secret_item: *mut SecretItemFFI, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_item_load_secrets_sync    (items: *mut GList, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_item_set_secret_sync      (secret_item: *mut SecretItemFFI, value: *mut SecretValueFFI, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_item_refresh              (secret_item: *mut SecretItemFFI);

    //=========================================================================
    // SecretValue
    //=========================================================================
    pub fn secret_value_new             (secret: *const gchar, length: gssize, content_type: *const gchar) -> *mut SecretValueFFI;
//  pub fn secret_value_new_full        ()
    pub fn secret_value_get             (secret_value: *mut SecretValueFFI, length: *mut gsize) -> *const gchar;
    pub fn secret_value_get_text        (secret_value: *mut SecretValueFFI) -> *const gchar;
    pub fn secret_value_get_content_type(secret_value: *mut SecretValueFFI) -> *const gchar;
    pub fn secret_value_ref             (secret_value: *mut SecretValueFFI) -> *mut SecretValueFFI;
    pub fn secret_value_unref           (value: gpointer);
}

#[test]
fn test_secret_service() {
    use std::ptr::null_mut;
    use glib_sys::{GTRUE, g_list_length, g_list_nth_data};
    use libc::c_uint;
    use std::ffi::CStr;
    use std::str;
    unsafe{
        let secret_service = secret_service_get_sync(SECRET_SERVICE_OPEN_SESSION.bits(), null_mut(), null_mut());
        assert!(secret_service_load_collections_sync(secret_service, null_mut(), null_mut()) == GTRUE);
        let secret_collections = secret_service_get_collections(secret_service);
        let no_collections = g_list_length(secret_collections);
        println!("Number of secret_collections: {}", no_collections);
        for i in 0 .. no_collections {
            let secret_collection = g_list_nth_data(secret_collections, i as c_uint) as *mut SecretCollectionFFI;
            let label_c = secret_collection_get_label(secret_collection);
            println!("Label {}: {}", i, str::from_utf8(CStr::from_ptr(label_c).to_bytes()).unwrap());
            assert!(secret_collection_load_items_sync(secret_collection, null_mut(), null_mut()) == GTRUE);
            let secret_items = secret_collection_get_items(secret_collection);
            let no_items = g_list_length(secret_items);
            println!("Number of secret_items: {}", no_items);
            assert!(secret_item_load_secrets_sync(secret_items, null_mut(), null_mut()) == GTRUE);
            for j in 0 .. no_items {
                let secret_item = g_list_nth_data(secret_items, j as c_uint) as *mut SecretItemFFI;

                //schema_name = chrome_libsecret_password_schema
                let secret_item_schema_name_c = secret_item_get_schema_name(secret_item);
                let secret_item_schema_name = str::from_utf8(CStr::from_ptr(secret_item_schema_name_c).to_bytes()).unwrap();

                //label = uri
                let secret_item_label_c = secret_item_get_label(secret_item);
                let secret_item_label = str::from_utf8(CStr::from_ptr(secret_item_label_c).to_bytes()).unwrap();

                //secret text: password
                let secret_value = secret_item_get_secret(secret_item);
                let secret_text_c = secret_value_get_text(secret_value);
                println!("Secret {}: Schema name - {}; Secret label - {};Secret text - {}", j, secret_item_schema_name, secret_item_label, str::from_utf8(CStr::from_ptr(secret_text_c).to_bytes()).unwrap());
            }
        }
    }
}
<commit_msg>Remove unnecessary testcase<commit_after>#![allow(non_camel_case_types)]
extern crate libc;
extern crate glib;

use libc::{c_uint, c_char, c_int, c_ulong, c_long};
use glib::ffi::{GError, GType, GList, gboolean, gsize, gpointer, GHashTable};

//glib stuff not provided by glib-rs
pub type gchar = c_char;
pub type gint = c_int;
pub type guint = c_uint;
pub type guint64 = c_ulong;
pub type gssize = c_long;
#[repr(C)] pub struct GCancellable;

//libsecret

#[repr(C)] pub struct SecretServiceFFI;
#[repr(C)] pub struct SecretSchemaFFI;
#[repr(C)] pub struct SecretCollectionFFI;
#[repr(C)] pub struct SecretItemFFI;
#[repr(C)] pub struct SecretValueFFI;

#[link(name="secret-1")]
extern "C" {
    //=========================================================================
    // SecretService
    //=========================================================================
    pub fn secret_service_get_sync              (flags: c_int, cancellable: *mut GCancellable, error: *mut *mut GError) -> *mut SecretServiceFFI;
    pub fn secret_service_disconnect            ();
    pub fn secret_service_open_sync             (service_gtype: GType, service_bus_name: *const gchar, flags: c_int, cancellable: *mut GCancellable, error: *mut *mut GError) -> *mut SecretServiceFFI;
    pub fn secret_service_get_collections       (secret_service: *mut SecretServiceFFI) -> *mut GList;
    pub fn secret_service_get_flags             (secret_service: *mut SecretServiceFFI) -> c_int;
    pub fn secret_service_get_session_algorithms(secret_service: *mut SecretServiceFFI) -> *const gchar;
    pub fn secret_service_ensure_session_sync   (secret_service: *mut SecretServiceFFI, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_service_load_collections_sync (secret_service: *mut SecretServiceFFI, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_service_search_sync           (secret_service: *mut SecretServiceFFI, secret_schema: *const SecretSchemaFFI, attributes: *mut GHashTable, flags: c_int, cancellable: *mut GCancellable, error: *mut *mut GError) -> *mut GList;
    pub fn secret_service_lock_sync             (secret_service: *mut SecretServiceFFI, objects: *mut GList, cancellable: *mut GCancellable, locked: *mut *mut GList, error: *mut *mut GError);
    pub fn secret_service_unlock_sync           (secret_service: *mut SecretServiceFFI, objects: *mut GList, cancellable: *mut GCancellable, unlocked: *mut *mut GList, error: *mut *mut GError) -> gint;
    pub fn secret_service_store_sync            (secret_service: *mut SecretServiceFFI, schema: *const SecretSchemaFFI, attributes: *mut GHashTable, collection: *const gchar, label: *const gchar, value: *mut SecretValueFFI, cancellable: *mut GCancellable, error: *mut *mut GError);
    pub fn secret_service_lookup_sync           (secret_service: *mut SecretServiceFFI, schema: *const SecretSchemaFFI, attributes: *mut GHashTable, cancellable: *mut GCancellable, error: *mut *mut GError) -> *mut SecretValueFFI;
    pub fn secret_service_clear_sync            (secret_service: *mut SecretServiceFFI, schema: *const SecretSchemaFFI, attributes: *mut GHashTable, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
//  pub fn secret_service_prompt_sync           ();
    pub fn secret_service_set_alias_sync        (secret_service: *mut SecretServiceFFI, alias: *const gchar, collection: *mut SecretCollectionFFI, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_service_get_collection_gtype  (secret_service: *mut SecretServiceFFI) -> GType;
    pub fn secret_service_get_item_gtype        (secret_service: *mut SecretServiceFFI) -> GType;

    //=========================================================================
    // SecretCollection
    //=========================================================================
    pub fn secret_collection_for_alias_sync (secret_service: *mut SecretServiceFFI, alias: *const gchar, flags: c_int, cancellable: *mut GCancellable, error: *mut *mut GError) -> *mut SecretCollectionFFI;
    pub fn secret_collection_load_items_sync(secret_collection: *mut SecretCollectionFFI, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_collection_create_sync    (secret_service: *mut SecretServiceFFI, label: *const gchar, alias: *const gchar, flags: c_int, cancellable: *mut GCancellable, error: *mut *mut GError) -> *mut SecretCollectionFFI;
    pub fn secret_collection_search_sync    (secret_collection: *mut SecretCollectionFFI, schema: *const SecretSchemaFFI, atrributes: *mut GHashTable, flags: c_int, cancellable: *mut GCancellable, error: *mut *mut GError) -> *mut GList;
    pub fn secret_collection_delete_sync    (secret_collection: *mut SecretCollectionFFI, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_collection_get_created    (secret_collection: *mut SecretCollectionFFI) -> guint64;
    pub fn secret_collection_get_service    (secret_collection: *mut SecretCollectionFFI) -> *mut SecretServiceFFI;
    pub fn secret_collection_get_flags      (secret_collection: *mut SecretCollectionFFI) -> c_int;
    pub fn secret_collection_get_items      (secret_collection: *mut SecretCollectionFFI) -> *mut GList;
    pub fn secret_collection_get_label      (secret_collection: *mut SecretCollectionFFI) -> *mut gchar;
    pub fn secret_collection_set_label_sync (secret_collection: *mut SecretCollectionFFI, label: *const gchar, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_collection_get_locked     (secret_collection: *mut SecretCollectionFFI) -> gboolean;
    pub fn secret_collection_get_modified   (secret_collection: *mut SecretCollectionFFI) -> guint64;
    pub fn secret_collection_refresh        (secret_collection: *mut SecretCollectionFFI);

    //=========================================================================
    // SecretItem
    //=========================================================================
    pub fn secret_item_create_sync          (secret_collection: *mut SecretCollectionFFI, schema: *const SecretSchemaFFI, attributes: *mut GHashTable, label: *const gchar, value: *mut SecretValueFFI, flags: c_int, cancellable: *mut GCancellable, error: *mut *mut GError) -> *mut SecretItemFFI;
    pub fn secret_item_delete_sync          (secret_item: *mut SecretItemFFI, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_item_get_schema_name      (secret_item: *mut SecretItemFFI) -> *mut gchar;
    pub fn secret_item_get_attributes       (secret_item: *mut SecretItemFFI) -> *mut GHashTable;
    pub fn secret_item_set_attributes_sync  (secret_item: *mut SecretItemFFI, schema: *const SecretSchemaFFI, attributes: *mut GHashTable, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_item_get_created          (secret_item: *mut SecretItemFFI) -> guint64;
    pub fn secret_item_get_label            (secret_item: *mut SecretItemFFI) -> *mut gchar;
    pub fn secret_item_set_label_sync       (secret_item: *mut SecretItemFFI, label: *const gchar, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_item_get_flags            (secret_item: *mut SecretItemFFI) -> c_int;
    pub fn secret_item_get_locked           (secret_item: *mut SecretItemFFI) -> gboolean;
    pub fn secret_item_get_modified         (secret_item: *mut SecretItemFFI) -> guint64;
    pub fn secret_item_get_service          (secret_item: *mut SecretItemFFI) -> *mut SecretServiceFFI;
    pub fn secret_item_get_secret           (secret_item: *mut SecretItemFFI) -> *mut SecretValueFFI;
    pub fn secret_item_load_secret_sync     (secret_item: *mut SecretItemFFI, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_item_load_secrets_sync    (items: *mut GList, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_item_set_secret_sync      (secret_item: *mut SecretItemFFI, value: *mut SecretValueFFI, cancellable: *mut GCancellable, error: *mut *mut GError) -> gboolean;
    pub fn secret_item_refresh              (secret_item: *mut SecretItemFFI);

    //=========================================================================
    // SecretValue
    //=========================================================================
    pub fn secret_value_new             (secret: *const gchar, length: gssize, content_type: *const gchar) -> *mut SecretValueFFI;
//  pub fn secret_value_new_full        ()
    pub fn secret_value_get             (secret_value: *mut SecretValueFFI, length: *mut gsize) -> *const gchar;
    pub fn secret_value_get_text        (secret_value: *mut SecretValueFFI) -> *const gchar;
    pub fn secret_value_get_content_type(secret_value: *mut SecretValueFFI) -> *const gchar;
    pub fn secret_value_ref             (secret_value: *mut SecretValueFFI) -> *mut SecretValueFFI;
    pub fn secret_value_unref           (value: gpointer);
}
<|endoftext|>


<commit_before>// This file is released under the same terms as Rust itself.

use crossbeam;
use db::{Db, PendingEntry};
use db::sqlite::SqliteDb;
use horrorshow::prelude::*;
use hyper::buffer::BufReader;
use hyper::header::{ContentType, Headers};
use hyper::net::{HttpListener, NetworkListener, NetworkStream};
use hyper::server::{Request, Response};
use hyper::status::StatusCode;
use hyper::uri::RequestUri;
use pipeline::PipelineId;
use std::collections::HashMap;
use std::convert::AsRef;
use std::error::Error;
use std::io::{BufWriter, Write};
use std::marker::PhantomData;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use ui::Pr;

const WORKER_COUNT: usize = 1;

pub fn run_sqlite
(
    listen: String,
    path: PathBuf,
    pipelines: HashMap<String, PipelineId>,
)
    where
::Err: Error,

::Err: Error
{
    let path: &Path = path.as_ref();
    let listen: &str = listen.as_ref();
    crossbeam::scope(|scope| {
        for _ in 0..WORKER_COUNT {
            let mut worker = Worker {
                db: SqliteDb::
::open(path)
                    .expect("opening sqlite to succeed"),
                pipelines: &pipelines,
                _pr: PhantomData::
,
            };
            scope.spawn(move || worker.run(listen));
        }
    });
}

struct Worker<'a, P, D>
    where P: Pr, D: Db

{
    db: D,
    pipelines: &'a HashMap<String, PipelineId>,
    _pr: PhantomData
,
}

impl<'a, P: Pr, D: Db
> Worker<'a, P, D> {
    fn run(&mut self, listen: &str) {
        let mut listener = HttpListener::new(listen).expect("a TCP socket");
        while let Ok(mut stream) = listener.accept() {
            let addr = stream.peer_addr()
                .expect("view client address");
            let mut stream_clone = stream.clone();
            let mut buf_read = BufReader::new(
                &mut stream_clone as &mut NetworkStream
            );
            let mut buf_write = BufWriter::new(&mut stream);
            let req = match Request::new(&mut buf_read, addr) {
                Ok(req) => req,
                Err(e) => {
                    warn!("Invalid view HTTP: {:?}", e);
                    continue;
                }
            };
            let mut head = Headers::new();
            let res = Response::new(&mut buf_write, &mut head);
            match self.handle_req(req, res) {
                Ok(()) => (),
                Err(e) => {
                    warn!("Failed to handle view request: {:?}", e);
                }
            }
        }
    }
    fn handle_req(
        &mut self,
        req: Request,
        mut res: Response,
    ) -> Result<(), Box<Error>> {
        let pipeline = if let RequestUri::AbsolutePath(ref path) = req.uri {
            let mut path = &path[..];
            if path == "/" {
                None
            } else {
                if path.as_bytes()[0] == b'/' {
                    path = &path[1..];
                }
                match self.pipelines.get(path) {
                    Some(pipeline_id) => {
                        *res.status_mut() = StatusCode::Ok;
                        Some((path.to_owned(), *pipeline_id))
                    }
                    None => {
                        *res.status_mut() = StatusCode::NotFound;
                        return Ok(());
                    }
                }
            }
        } else {
            *res.status_mut() = StatusCode::NotFound;
            return Ok(());
        };
        res.headers_mut().set(ContentType::html());
        let mut res = try!(res.start());
        try!(res.write_all(br##"<!DOCTYPE html>"##));
        if let Some((name, pipeline_id)) = pipeline {
            self.handle_pipeline_req(&name, pipeline_id, req, res)
        } else {
            self.handle_home_req(req, res)
        }
    }
    fn handle_pipeline_req(
        &mut self,
        name: &str,
        pipeline_id: PipelineId,
        _req: Request,
        mut res: Response<::hyper::net::Streaming>,
    ) -> Result<(), Box<Error>> {
        let pending_entries = self.db.list_pending(pipeline_id);
        let queued_entries = self.db.list_queue(pipeline_id);
        let running_entry = self.db.peek_running(pipeline_id);
        let mut running = None;
        let mut queued = Vec::new();
        let pending: Vec<_> = pending_entries.into_iter().filter_map(|entry| {
            if Some(&entry.pr) == running_entry.as_ref().map(|x| &x.pr) {
                running = Some(entry);
            } else if queued_entries.iter()
                    .filter(|q| q.pr == entry.pr)
                    .next().is_some() {
                queued.push(entry);
            } else {
                return Some(entry);
            }
            None
        }).collect();
        let html = html!{
            html {
                head {
                    title { : name }
                    link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.1.1/normalize.min.css");
                    style { : raw!(include_str!("style.css")) }
                }
                body {
                    h1 { : name }
                    table {
                        thead {
                            th { : "Status" }
                            th { : "PR#" }
                            th { : "Title" }
                        }
                        tbody {
                            |t| {
                                for entry in running {
                                    render_entry(State::Running, entry, t);
                                }
                                for entry in queued {
                                    render_entry(State::Queued, entry, t);
                                }
                                for entry in pending {
                                    render_entry(State::Pending, entry, t);
                                }
                            }
                        }
                    }
                }
            }
        };
        try!(html.write_to_io(&mut res));
        try!(res.end());
        Ok(())
    }
    fn handle_home_req(
        &mut self,
        _req: Request,
        mut res: Response<::hyper::net::Streaming>,
    ) -> Result<(), Box<Error>> {
        let html = html!{
            html {
                head {
                    title { : "Aelita" }
                    link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.1.1/normalize.min.css");
                    style { : raw!(include_str!("style.css")) }
                }
                body {
                    h1 { : "Repositories" }
                    table {
                        thead {
                            th { : "Name" }
                            th { : "Running" }
                            th { : "In queue" }
                            th { : "In review" }
                            th { : "Opened" }
                        }
                        tbody {
                            @ for (n, &pid) in self.pipelines { |t| {
                                let opened = self.db.list_pending(pid).len();
                                let queue = self.db.list_queue(pid).len();
                                let running = self.db.peek_running(pid).is_some();
                                let running = if running { 1 } else { 0 };
                                let review = opened - queue - running;
                                t << html!{
                                    tr {
                                        td(class="fill-link") {
                                            a(href=n) : { n }
                                        }
                                        td { : running }
                                        td { : queue }
                                        td { : review }
                                        td { : opened }
                                    }
                                }
                            }}
                        }
                    }
                    h2 { : "Github cheat sheet" }
                    p { : "To use the robot, say a command to it." }
                    dl {
                        dt { : raw!("r+") }
                        dd { : "Add the pull request to the merge queue." }
                        dt { : raw!("r=@username") }
                        dd { : "Add the pull request on behalf of \"username.\"" }
                        dt { : raw!("r-") }
                        dd { : "Cancel the pull request." }
                    }
                }
            }
        };
        try!(html.write_to_io(&mut res));
        try!(res.end());
        Ok(())
    }
}

enum State {
    Running,
    Queued,
    Pending,
}

fn render_entry
(
    state: State,
    entry: PendingEntry
,
    t: &mut TemplateBuffer,
) {
    t < "Running",
                    State::Queued => "In queue",
                    State::Pending => "In review",
                }
            }
            td(class="fill-link") {
                a(href=entry.url.to_string()) { : entry.pr.to_string() }
            }
            td { : &entry.title }
        }
    };
}<commit_msg>Add empty indicators<commit_after>// This file is released under the same terms as Rust itself.

use crossbeam;
use db::{Db, PendingEntry};
use db::sqlite::SqliteDb;
use horrorshow::prelude::*;
use hyper::buffer::BufReader;
use hyper::header::{ContentType, Headers};
use hyper::net::{HttpListener, NetworkListener, NetworkStream};
use hyper::server::{Request, Response};
use hyper::status::StatusCode;
use hyper::uri::RequestUri;
use pipeline::PipelineId;
use std::collections::HashMap;
use std::convert::AsRef;
use std::error::Error;
use std::io::{BufWriter, Write};
use std::marker::PhantomData;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use ui::Pr;

const WORKER_COUNT: usize = 1;

pub fn run_sqlite
(
    listen: String,
    path: PathBuf,
    pipelines: HashMap<String, PipelineId>,
)
    where
::Err: Error,

::Err: Error
{
    let path: &Path = path.as_ref();
    let listen: &str = listen.as_ref();
    crossbeam::scope(|scope| {
        for _ in 0..WORKER_COUNT {
            let mut worker = Worker {
                db: SqliteDb::
::open(path)
                    .expect("opening sqlite to succeed"),
                pipelines: &pipelines,
                _pr: PhantomData::
,
            };
            scope.spawn(move || worker.run(listen));
        }
    });
}

struct Worker<'a, P, D>
    where P: Pr, D: Db

{
    db: D,
    pipelines: &'a HashMap<String, PipelineId>,
    _pr: PhantomData
,
}

impl<'a, P: Pr, D: Db
> Worker<'a, P, D> {
    fn run(&mut self, listen: &str) {
        let mut listener = HttpListener::new(listen).expect("a TCP socket");
        while let Ok(mut stream) = listener.accept() {
            let addr = stream.peer_addr()
                .expect("view client address");
            let mut stream_clone = stream.clone();
            let mut buf_read = BufReader::new(
                &mut stream_clone as &mut NetworkStream
            );
            let mut buf_write = BufWriter::new(&mut stream);
            let req = match Request::new(&mut buf_read, addr) {
                Ok(req) => req,
                Err(e) => {
                    warn!("Invalid view HTTP: {:?}", e);
                    continue;
                }
            };
            let mut head = Headers::new();
            let res = Response::new(&mut buf_write, &mut head);
            match self.handle_req(req, res) {
                Ok(()) => (),
                Err(e) => {
                    warn!("Failed to handle view request: {:?}", e);
                }
            }
        }
    }
    fn handle_req(
        &mut self,
        req: Request,
        mut res: Response,
    ) -> Result<(), Box<Error>> {
        let pipeline = if let RequestUri::AbsolutePath(ref path) = req.uri {
            let mut path = &path[..];
            if path == "/" {
                None
            } else {
                if path.as_bytes()[0] == b'/' {
                    path = &path[1..];
                }
                match self.pipelines.get(path) {
                    Some(pipeline_id) => {
                        *res.status_mut() = StatusCode::Ok;
                        Some((path.to_owned(), *pipeline_id))
                    }
                    None => {
                        *res.status_mut() = StatusCode::NotFound;
                        return Ok(());
                    }
                }
            }
        } else {
            *res.status_mut() = StatusCode::NotFound;
            return Ok(());
        };
        res.headers_mut().set(ContentType::html());
        let mut res = try!(res.start());
        try!(res.write_all(br##"<!DOCTYPE html>"##));
        if let Some((name, pipeline_id)) = pipeline {
            self.handle_pipeline_req(&name, pipeline_id, req, res)
        } else {
            self.handle_home_req(req, res)
        }
    }
    fn handle_pipeline_req(
        &mut self,
        name: &str,
        pipeline_id: PipelineId,
        _req: Request,
        mut res: Response<::hyper::net::Streaming>,
    ) -> Result<(), Box<Error>> {
        let pending_entries = self.db.list_pending(pipeline_id);
        let is_empty = pending_entries.is_empty();
        let queued_entries = self.db.list_queue(pipeline_id);
        let running_entry = self.db.peek_running(pipeline_id);
        let mut running = None;
        let mut queued = Vec::new();
        let pending: Vec<_> = pending_entries.into_iter().filter_map(|entry| {
            if Some(&entry.pr) == running_entry.as_ref().map(|x| &x.pr) {
                running = Some(entry);
            } else if queued_entries.iter()
                    .filter(|q| q.pr == entry.pr)
                    .next().is_some() {
                queued.push(entry);
            } else {
                return Some(entry);
            }
            None
        }).collect();
        let html = html!{
            html {
                head {
                    title { : name }
                    link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.1.1/normalize.min.css");
                    style { : raw!(include_str!("style.css")) }
                }
                body {
                    h1 { : name }
                    table {
                        thead {
                            th { : "Status" }
                            th { : "PR#" }
                            th { : "Title" }
                        }
                        tbody {
                            |t| {
                                for entry in running {
                                    render_entry(State::Running, entry, t);
                                }
                                for entry in queued {
                                    render_entry(State::Queued, entry, t);
                                }
                                for entry in pending {
                                    render_entry(State::Pending, entry, t);
                                }
                                if is_empty {
                                    t << html!{
                                        td(colspan=3) {
                                            : "No opened pull requests"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        };
        try!(html.write_to_io(&mut res));
        try!(res.end());
        Ok(())
    }
    fn handle_home_req(
        &mut self,
        _req: Request,
        mut res: Response<::hyper::net::Streaming>,
    ) -> Result<(), Box<Error>> {
        let html = html!{
            html {
                head {
                    title { : "Aelita" }
                    link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.1.1/normalize.min.css");
                    style { : raw!(include_str!("style.css")) }
                }
                body {
                    h1 { : "Repositories" }
                    table {
                        thead {
                            th { : "Name" }
                            th { : "Running" }
                            th { : "In queue" }
                            th { : "In review" }
                            th { : "Opened" }
                        }
                        tbody {
                            @ for (n, &pid) in self.pipelines { |t| {
                                let opened = self.db.list_pending(pid).len();
                                let queue = self.db.list_queue(pid).len();
                                let running = self.db.peek_running(pid).is_some();
                                let running = if running { 1 } else { 0 };
                                let review = opened - queue - running;
                                t << html!{
                                    tr {
                                        td(class="fill-link") {
                                            a(href=n) : { n }
                                        }
                                        td { : running }
                                        td { : queue }
                                        td { : review }
                                        td { : opened }
                                    }
                                }
                            }}
                            @ if self.pipelines.is_empty() {
                                td(colspan=5) {
                                    : "No configured repositories"
                                }
                            }
                        }
                    }
                    h2 { : "Github cheat sheet" }
                    p { : "To use the robot, say a command to it." }
                    dl {
                        dt { : raw!("r+") }
                        dd { : "Add the pull request to the merge queue." }
                        dt { : raw!("r=@username") }
                        dd { : "Add the pull request on behalf of \"username.\"" }
                        dt { : raw!("r-") }
                        dd { : "Cancel the pull request." }
                    }
                }
            }
        };
        try!(html.write_to_io(&mut res));
        try!(res.end());
        Ok(())
    }
}

enum State {
    Running,
    Queued,
    Pending,
}

fn render_entry
(
    state: State,
    entry: PendingEntry
,
    t: &mut TemplateBuffer,
) {
    t < "Running",
                    State::Queued => "In queue",
                    State::Pending => "In review",
                }
            }
            td(class="fill-link") {
                a(href=entry.url.to_string()) { : entry.pr.to_string() }
            }
            td { : &entry.title }
        }
    };
}<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("InheritedBox", inherited=True, gecko_name="Visibility") %>

${helpers.single_keyword("direction", "ltr rtl", need_clone=True, animatable=False)}

// TODO: collapse. Well, do tables first.
${helpers.single_keyword("visibility",
                         "visible hidden",
                         extra_gecko_values="collapse",
                         gecko_ffi_name="mVisible",
                         animatable=True)}

// CSS Writing Modes Level 3
// http://dev.w3.org/csswg/css-writing-modes/
${helpers.single_keyword("writing-mode",
                         "horizontal-tb vertical-rl vertical-lr",
                         experimental=True,
                         need_clone=True,
                         animatable=False)}

// FIXME(SimonSapin): Add 'mixed' and 'upright' (needs vertical text support)
// FIXME(SimonSapin): initial (first) value should be 'mixed', when that's implemented
// FIXME(bholley): sideways-right is needed as an alias to sideways in gecko.
${helpers.single_keyword("text-orientation",
                         "sideways",
                         experimental=True,
                         need_clone=True,
                         extra_gecko_values="mixed upright",
                         extra_servo_values="sideways-right sideways-left",
                         animatable=False)}

// CSS Color Module Level 4
// https://drafts.csswg.org/css-color/
${helpers.single_keyword("color-adjust",
                         "economy exact", products="gecko",
                         animatable=False)}

<% image_rendering_custom_consts = { "crisp-edges": "CRISPEDGES" } %>
// According to to CSS-IMAGES-3, `optimizespeed` and `optimizequality` are synonyms for `auto`
// And, firefox doesn't support `pixelated` yet (https://bugzilla.mozilla.org/show_bug.cgi?id=856337)
${helpers.single_keyword("image-rendering",
                         "auto crisp-edges",
                         extra_gecko_values="optimizespeed optimizequality",
                         extra_servo_values="pixelated",
                         custom_consts=image_rendering_custom_consts,
                         animatable=False)}

// Image Orientation
// https://drafts.csswg.org/css-images/#the-image-orientation
<%helpers:longhand name="image-orientation"
                   products="None"
                   animatable="False">
    use std::fmt;
    use style_traits::ToCss;
    use values::specified::Angle;

    use values::NoViewportPercentage;
    impl NoViewportPercentage for SpecifiedValue {}

    use std::f32::consts::PI;
    use values::CSSFloat;
    const TWO_PI: CSSFloat = 2.0*PI;

    #[derive(Clone, PartialEq, Copy, Debug)]
    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
    pub struct SpecifiedValue {
        pub angle: Option<Angle>,
        pub flipped: bool
    }

    impl ToCss for SpecifiedValue {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            if let Some(angle) = self.angle {
                try!(angle.to_css(dest));
                if self.flipped {
                    dest.write_str(" flipped")
                } else {
                    Ok(())
                }
            } else {
                if self.flipped {
                    dest.write_str("flipped")
                } else {
                    dest.write_str("from-image")
                }
            }
        }
    }

    pub mod computed_value {
        use values::specified::Angle;

        #[derive(Clone, PartialEq, Copy, Debug)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        pub enum T {
            FromImage,
            AngleWithFlipped(Angle, bool),
        }
    }

    const INITIAL_ANGLE: Angle = Angle(0.0);

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        computed_value::T::AngleWithFlipped(INITIAL_ANGLE, false)
    }

    // According to CSS Content Module Level 3:
    // The computed value of the property is calculated by rounding the specified angle
    // to the nearest quarter-turn, rounding away from 0, then moduloing the value by 1 turn.
    #[inline]
    fn normalize_angle(angle: &Angle) -> Angle {
        let radians = angle.radians();
        let rounded_quarter_turns = (4.0 * radians / TWO_PI).round();
        let normalized_quarter_turns = (rounded_quarter_turns % 4.0 + 4.0) % 4.0;
        let normalized_radians = normalized_quarter_turns/4.0 * TWO_PI;
        Angle::from_radians(normalized_radians)
    }

    impl ToComputedValue for SpecifiedValue {
        type ComputedValue = computed_value::T;

        #[inline]
        fn to_computed_value(&self, _: &Context) -> computed_value::T {
            if let Some(ref angle) = self.angle {
                let normalized_angle = normalize_angle(angle);
                computed_value::T::AngleWithFlipped(normalized_angle, self.flipped)
            } else {
                if self.flipped {
                    computed_value::T::AngleWithFlipped(INITIAL_ANGLE, true)
                } else {
                    computed_value::T::FromImage
                }
            }
        }

        #[inline]
        fn from_computed_value(computed: &computed_value::T) -> Self {
            match *computed {
                computed_value::T::FromImage => SpecifiedValue { angle: None, flipped: false },
                computed_value::T::AngleWithFlipped(angle, flipped) =>
                    SpecifiedValue { angle: Some(angle), flipped: flipped },
            }
        }
    }

    impl ToCss for computed_value::T {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            match *self {
                computed_value::T::FromImage => dest.write_str("from-image"),
                computed_value::T::AngleWithFlipped(angle, flipped) => {
                    try!(angle.to_css(dest));
                    if flipped {
                        try!(dest.write_str(" flipped"));
                    }
                    Ok(())
                },
            }
        }
    }

    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
        if input.try(|input| input.expect_ident_matching("from-image")).is_ok() {
            // Handle from-image
            Ok(SpecifiedValue { angle: None, flipped: false })
        } else {
            // Handle <angle> | <angle>? flip
            let angle = input.try(|input| Angle::parse(context, input)).ok();
            let flipped = input.try(|input| input.expect_ident_matching("flip")).is_ok();
            let explicit_angle = if angle.is_none() && !flipped {
                Some(INITIAL_ANGLE)
            } else {
                angle
            };

            Ok(SpecifiedValue { angle: explicit_angle, flipped: flipped })
        }
    }
</%helpers:longhand>

// Used in the bottom-up flow construction traversal to avoid constructing flows for
// descendants of nodes with `display: none`.
<%helpers:longhand name="-servo-under-display-none"
                   derived_from="display"
                   products="servo"
                   animatable="False">
    use std::fmt;
    use style_traits::ToCss;
    use values::computed::ComputedValueAsSpecified;
    use values::NoViewportPercentage;

    impl NoViewportPercentage for SpecifiedValue {}

    #[derive(Copy, Clone, Debug, Eq, PartialEq)]
    #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
    pub struct SpecifiedValue(pub bool);

    pub mod computed_value {
        pub type T = super::SpecifiedValue;
    }
    impl ComputedValueAsSpecified for SpecifiedValue {}

    pub fn get_initial_value() -> computed_value::T {
        SpecifiedValue(false)
    }

    impl ToCss for SpecifiedValue {
        fn to_css<W>(&self, _: &mut W) -> fmt::Result where W: fmt::Write {
            Ok(()) // Internal property
        }
    }

    #[inline]
    pub fn derive_from_display(context: &mut Context) {
        use super::display::computed_value::T as Display;

        if context.style().get_box().clone_display() == Display::none {
            context.mutate_style().mutate_inheritedbox()
                                  .set__servo_under_display_none(SpecifiedValue(true));
        }
    }
</%helpers:longhand>
<commit_msg>Add spec links for inherited_box properties<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("InheritedBox", inherited=True, gecko_name="Visibility") %>

// TODO: collapse. Well, do tables first.
${helpers.single_keyword("visibility",
                         "visible hidden",
                         extra_gecko_values="collapse",
                         gecko_ffi_name="mVisible",
                         animatable=True,
                         spec="https://drafts.csswg.org/css-box/#propdef-visibility")}

// CSS Writing Modes Level 3
// https://drafts.csswg.org/css-writing-modes-3
${helpers.single_keyword("writing-mode",
                         "horizontal-tb vertical-rl vertical-lr",
                         experimental=True,
                         need_clone=True,
                         animatable=False,
                         spec="https://drafts.csswg.org/css-writing-modes/#propdef-writing-mode")}

${helpers.single_keyword("direction", "ltr rtl", need_clone=True, animatable=False,
                         spec="https://drafts.csswg.org/css-writing-modes/#propdef-direction")}

// FIXME(SimonSapin): Add 'mixed' and 'upright' (needs vertical text support)
// FIXME(SimonSapin): initial (first) value should be 'mixed', when that's implemented
// FIXME(bholley): sideways-right is needed as an alias to sideways in gecko.
${helpers.single_keyword("text-orientation",
                         "sideways",
                         experimental=True,
                         need_clone=True,
                         extra_gecko_values="mixed upright",
                         extra_servo_values="sideways-right sideways-left",
                         animatable=False,
                         spec="https://drafts.csswg.org/css-writing-modes/#propdef-text-orientation")}

// CSS Color Module Level 4
// https://drafts.csswg.org/css-color/
${helpers.single_keyword("color-adjust",
                         "economy exact", products="gecko",
                         animatable=False,
                         spec="https://drafts.csswg.org/css-color/#propdef-color-adjust")}

<% image_rendering_custom_consts = { "crisp-edges": "CRISPEDGES" } %>
// According to to CSS-IMAGES-3, `optimizespeed` and `optimizequality` are synonyms for `auto`
// And, firefox doesn't support `pixelated` yet (https://bugzilla.mozilla.org/show_bug.cgi?id=856337)
${helpers.single_keyword("image-rendering",
                         "auto crisp-edges",
                         extra_gecko_values="optimizespeed optimizequality",
                         extra_servo_values="pixelated",
                         custom_consts=image_rendering_custom_consts,
                         animatable=False,
                         spec="https://drafts.csswg.org/css-images/#propdef-image-rendering")}

// Image Orientation
<%helpers:longhand name="image-orientation"
                   products="None"
                   animatable="False"
                   spec="https://drafts.csswg.org/css-images/#propdef-image-orientation, \
                         additional values in https://developer.mozilla.org/en-US/docs/Web/CSS/image-orientation">
    use std::fmt;
    use style_traits::ToCss;
    use values::specified::Angle;

    use values::NoViewportPercentage;
    impl NoViewportPercentage for SpecifiedValue {}

    use std::f32::consts::PI;
    use values::CSSFloat;
    const TWO_PI: CSSFloat = 2.0*PI;

    #[derive(Clone, PartialEq, Copy, Debug)]
    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
    pub struct SpecifiedValue {
        pub angle: Option<Angle>,
        pub flipped: bool
    }

    impl ToCss for SpecifiedValue {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            if let Some(angle) = self.angle {
                try!(angle.to_css(dest));
                if self.flipped {
                    dest.write_str(" flipped")
                } else {
                    Ok(())
                }
            } else {
                if self.flipped {
                    dest.write_str("flipped")
                } else {
                    dest.write_str("from-image")
                }
            }
        }
    }

    pub mod computed_value {
        use values::specified::Angle;

        #[derive(Clone, PartialEq, Copy, Debug)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        pub enum T {
            FromImage,
            AngleWithFlipped(Angle, bool),
        }
    }

    const INITIAL_ANGLE: Angle = Angle(0.0);

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        computed_value::T::AngleWithFlipped(INITIAL_ANGLE, false)
    }

    // According to CSS Content Module Level 3:
    // The computed value of the property is calculated by rounding the specified angle
    // to the nearest quarter-turn, rounding away from 0, then moduloing the value by 1 turn.
    #[inline]
    fn normalize_angle(angle: &Angle) -> Angle {
        let radians = angle.radians();
        let rounded_quarter_turns = (4.0 * radians / TWO_PI).round();
        let normalized_quarter_turns = (rounded_quarter_turns % 4.0 + 4.0) % 4.0;
        let normalized_radians = normalized_quarter_turns/4.0 * TWO_PI;
        Angle::from_radians(normalized_radians)
    }

    impl ToComputedValue for SpecifiedValue {
        type ComputedValue = computed_value::T;

        #[inline]
        fn to_computed_value(&self, _: &Context) -> computed_value::T {
            if let Some(ref angle) = self.angle {
                let normalized_angle = normalize_angle(angle);
                computed_value::T::AngleWithFlipped(normalized_angle, self.flipped)
            } else {
                if self.flipped {
                    computed_value::T::AngleWithFlipped(INITIAL_ANGLE, true)
                } else {
                    computed_value::T::FromImage
                }
            }
        }

        #[inline]
        fn from_computed_value(computed: &computed_value::T) -> Self {
            match *computed {
                computed_value::T::FromImage => SpecifiedValue { angle: None, flipped: false },
                computed_value::T::AngleWithFlipped(angle, flipped) =>
                    SpecifiedValue { angle: Some(angle), flipped: flipped },
            }
        }
    }

    impl ToCss for computed_value::T {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            match *self {
                computed_value::T::FromImage => dest.write_str("from-image"),
                computed_value::T::AngleWithFlipped(angle, flipped) => {
                    try!(angle.to_css(dest));
                    if flipped {
                        try!(dest.write_str(" flipped"));
                    }
                    Ok(())
                },
            }
        }
    }

    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
        if input.try(|input| input.expect_ident_matching("from-image")).is_ok() {
            // Handle from-image
            Ok(SpecifiedValue { angle: None, flipped: false })
        } else {
            // Handle <angle> | <angle>? flip
            let angle = input.try(|input| Angle::parse(context, input)).ok();
            let flipped = input.try(|input| input.expect_ident_matching("flip")).is_ok();
            let explicit_angle = if angle.is_none() && !flipped {
                Some(INITIAL_ANGLE)
            } else {
                angle
            };

            Ok(SpecifiedValue { angle: explicit_angle, flipped: flipped })
        }
    }
</%helpers:longhand>

// Used in the bottom-up flow construction traversal to avoid constructing flows for
// descendants of nodes with `display: none`.
<%helpers:longhand name="-servo-under-display-none"
                   derived_from="display"
                   products="servo"
                   animatable="False"
                   spec="Nonstandard (internal layout use only)">
    use std::fmt;
    use style_traits::ToCss;
    use values::computed::ComputedValueAsSpecified;
    use values::NoViewportPercentage;

    impl NoViewportPercentage for SpecifiedValue {}

    #[derive(Copy, Clone, Debug, Eq, PartialEq)]
    #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
    pub struct SpecifiedValue(pub bool);

    pub mod computed_value {
        pub type T = super::SpecifiedValue;
    }
    impl ComputedValueAsSpecified for SpecifiedValue {}

    pub fn get_initial_value() -> computed_value::T {
        SpecifiedValue(false)
    }

    impl ToCss for SpecifiedValue {
        fn to_css<W>(&self, _: &mut W) -> fmt::Result where W: fmt::Write {
            Ok(()) // Internal property
        }
    }

    #[inline]
    pub fn derive_from_display(context: &mut Context) {
        use super::display::computed_value::T as Display;

        if context.style().get_box().clone_display() == Display::none {
            context.mutate_style().mutate_inheritedbox()
                                  .set__servo_under_display_none(SpecifiedValue(true));
        }
    }
</%helpers:longhand>
<|endoftext|>


<commit_before>use crate::syntax::{
    Array, ExternFn, Impl, Include, Lifetimes, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
};
use std::hash::{Hash, Hasher};
use std::mem;
use std::ops::{Deref, DerefMut};

impl PartialEq for Include {
    fn eq(&self, other: &Include) -> bool {
        let Include {
            path,
            kind,
            begin_span: _,
            end_span: _,
        } = self;
        let Include {
            path: path2,
            kind: kind2,
            begin_span: _,
            end_span: _,
        } = other;
        path == path2 && kind == kind2
    }
}

impl Deref for ExternFn {
    type Target = Signature;

    fn deref(&self) -> &Self::Target {
        &self.sig
    }
}

impl DerefMut for ExternFn {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.sig
    }
}

impl Hash for Type {
    fn hash<H: Hasher>(&self, state: &mut H) {
        mem::discriminant(self).hash(state);
        match self {
            Type::Ident(t) => t.hash(state),
            Type::RustBox(t) => t.hash(state),
            Type::UniquePtr(t) => t.hash(state),
            Type::SharedPtr(t) => t.hash(state),
            Type::WeakPtr(t) => t.hash(state),
            Type::Ref(t) => t.hash(state),
            Type::Str(t) => t.hash(state),
            Type::RustVec(t) => t.hash(state),
            Type::CxxVector(t) => t.hash(state),
            Type::Fn(t) => t.hash(state),
            Type::SliceRef(t) => t.hash(state),
            Type::Array(t) => t.hash(state),
            Type::Void(_) => {}
        }
    }
}

impl Eq for Type {}

impl PartialEq for Type {
    fn eq(&self, other: &Type) -> bool {
        match (self, other) {
            (Type::Ident(lhs), Type::Ident(rhs)) => lhs == rhs,
            (Type::RustBox(lhs), Type::RustBox(rhs)) => lhs == rhs,
            (Type::UniquePtr(lhs), Type::UniquePtr(rhs)) => lhs == rhs,
            (Type::SharedPtr(lhs), Type::SharedPtr(rhs)) => lhs == rhs,
            (Type::WeakPtr(lhs), Type::WeakPtr(rhs)) => lhs == rhs,
            (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
            (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
            (Type::RustVec(lhs), Type::RustVec(rhs)) => lhs == rhs,
            (Type::CxxVector(lhs), Type::CxxVector(rhs)) => lhs == rhs,
            (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
            (Type::SliceRef(lhs), Type::SliceRef(rhs)) => lhs == rhs,
            (Type::Void(_), Type::Void(_)) => true,
            (_, _) => false,
        }
    }
}

impl Eq for Lifetimes {}

impl PartialEq for Lifetimes {
    fn eq(&self, other: &Lifetimes) -> bool {
        let Lifetimes {
            lt_token: _,
            lifetimes,
            gt_token: _,
        } = self;
        let Lifetimes {
            lt_token: _,
            lifetimes: lifetimes2,
            gt_token: _,
        } = other;
        lifetimes.iter().eq(lifetimes2)
    }
}

impl Hash for Lifetimes {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Lifetimes {
            lt_token: _,
            lifetimes,
            gt_token: _,
        } = self;
        lifetimes.len().hash(state);
        for lifetime in lifetimes {
            lifetime.hash(state);
        }
    }
}

impl Eq for Ty1 {}

impl PartialEq for Ty1 {
    fn eq(&self, other: &Ty1) -> bool {
        let Ty1 {
            name,
            langle: _,
            inner,
            rangle: _,
        } = self;
        let Ty1 {
            name: name2,
            langle: _,
            inner: inner2,
            rangle: _,
        } = other;
        name == name2 && inner == inner2
    }
}

impl Hash for Ty1 {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Ty1 {
            name,
            langle: _,
            inner,
            rangle: _,
        } = self;
        name.hash(state);
        inner.hash(state);
    }
}

impl Eq for Ref {}

impl PartialEq for Ref {
    fn eq(&self, other: &Ref) -> bool {
        let Ref {
            pinned,
            ampersand: _,
            lifetime,
            mutable,
            inner,
            pin_tokens: _,
            mutability: _,
        } = self;
        let Ref {
            pinned: pinned2,
            ampersand: _,
            lifetime: lifetime2,
            mutable: mutable2,
            inner: inner2,
            pin_tokens: _,
            mutability: _,
        } = other;
        pinned == pinned2 && lifetime == lifetime2 && mutable == mutable2 && inner == inner2
    }
}

impl Hash for Ref {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Ref {
            pinned,
            ampersand: _,
            lifetime,
            mutable,
            inner,
            pin_tokens: _,
            mutability: _,
        } = self;
        pinned.hash(state);
        lifetime.hash(state);
        mutable.hash(state);
        inner.hash(state);
    }
}

impl Eq for SliceRef {}

impl PartialEq for SliceRef {
    fn eq(&self, other: &SliceRef) -> bool {
        let SliceRef {
            ampersand: _,
            lifetime,
            mutable,
            bracket: _,
            inner,
            mutability: _,
        } = self;
        let SliceRef {
            ampersand: _,
            lifetime: lifetime2,
            mutable: mutable2,
            bracket: _,
            inner: inner2,
            mutability: _,
        } = other;
        lifetime == lifetime2 && mutable == mutable2 && inner == inner2
    }
}

impl Hash for SliceRef {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let SliceRef {
            ampersand: _,
            lifetime,
            mutable,
            bracket: _,
            inner,
            mutability: _,
        } = self;
        lifetime.hash(state);
        mutable.hash(state);
        inner.hash(state);
    }
}

impl Eq for Array {}

impl PartialEq for Array {
    fn eq(&self, other: &Array) -> bool {
        let Array {
            bracket: _,
            inner,
            semi_token: _,
            len,
            len_token: _,
        } = self;
        let Array {
            bracket: _,
            inner: inner2,
            semi_token: _,
            len: len2,
            len_token: _,
        } = other;
        inner == inner2 && len == len2
    }
}

impl Hash for Array {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Array {
            bracket: _,
            inner,
            semi_token: _,
            len,
            len_token: _,
        } = self;
        inner.hash(state);
        len.hash(state);
    }
}

impl Eq for Signature {}

impl PartialEq for Signature {
    fn eq(&self, other: &Signature) -> bool {
        let Signature {
            unsafety,
            fn_token: _,
            generics: _,
            receiver,
            args,
            ret,
            throws,
            paren_token: _,
            throws_tokens: _,
        } = self;
        let Signature {
            unsafety: unsafety2,
            fn_token: _,
            generics: _,
            receiver: receiver2,
            args: args2,
            ret: ret2,
            throws: throws2,
            paren_token: _,
            throws_tokens: _,
        } = other;
        unsafety.is_some() == unsafety2.is_some()
            && receiver == receiver2
            && ret == ret2
            && throws == throws2
            && args.len() == args2.len()
            && args.iter().zip(args2).all(|(arg, arg2)| {
                let Var {
                    doc: _,
                    attrs: _,
                    visibility: _,
                    name: _,
                    ty,
                } = arg;
                let Var {
                    doc: _,
                    attrs: _,
                    visibility: _,
                    name: _,
                    ty: ty2,
                } = arg2;
                ty == ty2
            })
    }
}

impl Hash for Signature {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Signature {
            unsafety,
            fn_token: _,
            generics: _,
            receiver,
            args,
            ret,
            throws,
            paren_token: _,
            throws_tokens: _,
        } = self;
        unsafety.is_some().hash(state);
        receiver.hash(state);
        for arg in args {
            let Var {
                doc: _,
                attrs: _,
                visibility: _,
                name: _,
                ty,
            } = arg;
            ty.hash(state);
        }
        ret.hash(state);
        throws.hash(state);
    }
}

impl Eq for Receiver {}

impl PartialEq for Receiver {
    fn eq(&self, other: &Receiver) -> bool {
        let Receiver {
            pinned,
            ampersand: _,
            lifetime,
            mutable,
            var: _,
            ty,
            shorthand: _,
            pin_tokens: _,
            mutability: _,
        } = self;
        let Receiver {
            pinned: pinned2,
            ampersand: _,
            lifetime: lifetime2,
            mutable: mutable2,
            var: _,
            ty: ty2,
            shorthand: _,
            pin_tokens: _,
            mutability: _,
        } = other;
        pinned == pinned2 && lifetime == lifetime2 && mutable == mutable2 && ty == ty2
    }
}

impl Hash for Receiver {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Receiver {
            pinned,
            ampersand: _,
            lifetime,
            mutable,
            var: _,
            ty,
            shorthand: _,
            pin_tokens: _,
            mutability: _,
        } = self;
        pinned.hash(state);
        lifetime.hash(state);
        mutable.hash(state);
        ty.hash(state);
    }
}

impl Hash for Impl {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Impl {
            impl_token: _,
            generics,
            negative,
            ty,
            brace_token: _,
            negative_token: _,
        } = self;
        generics.hash(state);
        if *negative {
            negative.hash(state);
        }
        ty.hash(state);
    }
}

impl Eq for Impl {}

impl PartialEq for Impl {
    fn eq(&self, other: &Impl) -> bool {
        let Impl {
            impl_token: _,
            generics,
            negative,
            ty,
            brace_token: _,
            negative_token: _,
        } = self;
        let Impl {
            impl_token: _,
            generics: generics2,
            negative: negative2,
            ty: ty2,
            brace_token: _,
            negative_token: _,
        } = other;
        generics == generics2 && negative == negative2 && ty == ty2
    }
}
<commit_msg>Remove unused Impl hashing impls<commit_after>use crate::syntax::{
    Array, ExternFn, Include, Lifetimes, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
};
use std::hash::{Hash, Hasher};
use std::mem;
use std::ops::{Deref, DerefMut};

impl PartialEq for Include {
    fn eq(&self, other: &Include) -> bool {
        let Include {
            path,
            kind,
            begin_span: _,
            end_span: _,
        } = self;
        let Include {
            path: path2,
            kind: kind2,
            begin_span: _,
            end_span: _,
        } = other;
        path == path2 && kind == kind2
    }
}

impl Deref for ExternFn {
    type Target = Signature;

    fn deref(&self) -> &Self::Target {
        &self.sig
    }
}

impl DerefMut for ExternFn {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.sig
    }
}

impl Hash for Type {
    fn hash<H: Hasher>(&self, state: &mut H) {
        mem::discriminant(self).hash(state);
        match self {
            Type::Ident(t) => t.hash(state),
            Type::RustBox(t) => t.hash(state),
            Type::UniquePtr(t) => t.hash(state),
            Type::SharedPtr(t) => t.hash(state),
            Type::WeakPtr(t) => t.hash(state),
            Type::Ref(t) => t.hash(state),
            Type::Str(t) => t.hash(state),
            Type::RustVec(t) => t.hash(state),
            Type::CxxVector(t) => t.hash(state),
            Type::Fn(t) => t.hash(state),
            Type::SliceRef(t) => t.hash(state),
            Type::Array(t) => t.hash(state),
            Type::Void(_) => {}
        }
    }
}

impl Eq for Type {}

impl PartialEq for Type {
    fn eq(&self, other: &Type) -> bool {
        match (self, other) {
            (Type::Ident(lhs), Type::Ident(rhs)) => lhs == rhs,
            (Type::RustBox(lhs), Type::RustBox(rhs)) => lhs == rhs,
            (Type::UniquePtr(lhs), Type::UniquePtr(rhs)) => lhs == rhs,
            (Type::SharedPtr(lhs), Type::SharedPtr(rhs)) => lhs == rhs,
            (Type::WeakPtr(lhs), Type::WeakPtr(rhs)) => lhs == rhs,
            (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
            (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
            (Type::RustVec(lhs), Type::RustVec(rhs)) => lhs == rhs,
            (Type::CxxVector(lhs), Type::CxxVector(rhs)) => lhs == rhs,
            (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
            (Type::SliceRef(lhs), Type::SliceRef(rhs)) => lhs == rhs,
            (Type::Void(_), Type::Void(_)) => true,
            (_, _) => false,
        }
    }
}

impl Eq for Lifetimes {}

impl PartialEq for Lifetimes {
    fn eq(&self, other: &Lifetimes) -> bool {
        let Lifetimes {
            lt_token: _,
            lifetimes,
            gt_token: _,
        } = self;
        let Lifetimes {
            lt_token: _,
            lifetimes: lifetimes2,
            gt_token: _,
        } = other;
        lifetimes.iter().eq(lifetimes2)
    }
}

impl Hash for Lifetimes {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Lifetimes {
            lt_token: _,
            lifetimes,
            gt_token: _,
        } = self;
        lifetimes.len().hash(state);
        for lifetime in lifetimes {
            lifetime.hash(state);
        }
    }
}

impl Eq for Ty1 {}

impl PartialEq for Ty1 {
    fn eq(&self, other: &Ty1) -> bool {
        let Ty1 {
            name,
            langle: _,
            inner,
            rangle: _,
        } = self;
        let Ty1 {
            name: name2,
            langle: _,
            inner: inner2,
            rangle: _,
        } = other;
        name == name2 && inner == inner2
    }
}

impl Hash for Ty1 {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Ty1 {
            name,
            langle: _,
            inner,
            rangle: _,
        } = self;
        name.hash(state);
        inner.hash(state);
    }
}

impl Eq for Ref {}

impl PartialEq for Ref {
    fn eq(&self, other: &Ref) -> bool {
        let Ref {
            pinned,
            ampersand: _,
            lifetime,
            mutable,
            inner,
            pin_tokens: _,
            mutability: _,
        } = self;
        let Ref {
            pinned: pinned2,
            ampersand: _,
            lifetime: lifetime2,
            mutable: mutable2,
            inner: inner2,
            pin_tokens: _,
            mutability: _,
        } = other;
        pinned == pinned2 && lifetime == lifetime2 && mutable == mutable2 && inner == inner2
    }
}

impl Hash for Ref {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Ref {
            pinned,
            ampersand: _,
            lifetime,
            mutable,
            inner,
            pin_tokens: _,
            mutability: _,
        } = self;
        pinned.hash(state);
        lifetime.hash(state);
        mutable.hash(state);
        inner.hash(state);
    }
}

impl Eq for SliceRef {}

impl PartialEq for SliceRef {
    fn eq(&self, other: &SliceRef) -> bool {
        let SliceRef {
            ampersand: _,
            lifetime,
            mutable,
            bracket: _,
            inner,
            mutability: _,
        } = self;
        let SliceRef {
            ampersand: _,
            lifetime: lifetime2,
            mutable: mutable2,
            bracket: _,
            inner: inner2,
            mutability: _,
        } = other;
        lifetime == lifetime2 && mutable == mutable2 && inner == inner2
    }
}

impl Hash for SliceRef {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let SliceRef {
            ampersand: _,
            lifetime,
            mutable,
            bracket: _,
            inner,
            mutability: _,
        } = self;
        lifetime.hash(state);
        mutable.hash(state);
        inner.hash(state);
    }
}

impl Eq for Array {}

impl PartialEq for Array {
    fn eq(&self, other: &Array) -> bool {
        let Array {
            bracket: _,
            inner,
            semi_token: _,
            len,
            len_token: _,
        } = self;
        let Array {
            bracket: _,
            inner: inner2,
            semi_token: _,
            len: len2,
            len_token: _,
        } = other;
        inner == inner2 && len == len2
    }
}

impl Hash for Array {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Array {
            bracket: _,
            inner,
            semi_token: _,
            len,
            len_token: _,
        } = self;
        inner.hash(state);
        len.hash(state);
    }
}

impl Eq for Signature {}

impl PartialEq for Signature {
    fn eq(&self, other: &Signature) -> bool {
        let Signature {
            unsafety,
            fn_token: _,
            generics: _,
            receiver,
            args,
            ret,
            throws,
            paren_token: _,
            throws_tokens: _,
        } = self;
        let Signature {
            unsafety: unsafety2,
            fn_token: _,
            generics: _,
            receiver: receiver2,
            args: args2,
            ret: ret2,
            throws: throws2,
            paren_token: _,
            throws_tokens: _,
        } = other;
        unsafety.is_some() == unsafety2.is_some()
            && receiver == receiver2
            && ret == ret2
            && throws == throws2
            && args.len() == args2.len()
            && args.iter().zip(args2).all(|(arg, arg2)| {
                let Var {
                    doc: _,
                    attrs: _,
                    visibility: _,
                    name: _,
                    ty,
                } = arg;
                let Var {
                    doc: _,
                    attrs: _,
                    visibility: _,
                    name: _,
                    ty: ty2,
                } = arg2;
                ty == ty2
            })
    }
}

impl Hash for Signature {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Signature {
            unsafety,
            fn_token: _,
            generics: _,
            receiver,
            args,
            ret,
            throws,
            paren_token: _,
            throws_tokens: _,
        } = self;
        unsafety.is_some().hash(state);
        receiver.hash(state);
        for arg in args {
            let Var {
                doc: _,
                attrs: _,
                visibility: _,
                name: _,
                ty,
            } = arg;
            ty.hash(state);
        }
        ret.hash(state);
        throws.hash(state);
    }
}

impl Eq for Receiver {}

impl PartialEq for Receiver {
    fn eq(&self, other: &Receiver) -> bool {
        let Receiver {
            pinned,
            ampersand: _,
            lifetime,
            mutable,
            var: _,
            ty,
            shorthand: _,
            pin_tokens: _,
            mutability: _,
        } = self;
        let Receiver {
            pinned: pinned2,
            ampersand: _,
            lifetime: lifetime2,
            mutable: mutable2,
            var: _,
            ty: ty2,
            shorthand: _,
            pin_tokens: _,
            mutability: _,
        } = other;
        pinned == pinned2 && lifetime == lifetime2 && mutable == mutable2 && ty == ty2
    }
}

impl Hash for Receiver {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let Receiver {
            pinned,
            ampersand: _,
            lifetime,
            mutable,
            var: _,
            ty,
            shorthand: _,
            pin_tokens: _,
            mutability: _,
        } = self;
        pinned.hash(state);
        lifetime.hash(state);
        mutable.hash(state);
        ty.hash(state);
    }
}
<|endoftext|>


<commit_before>// Tifflin OS Project
// - By John Hodge (thePowersGang)
//
// syscalls.inc.rs
// - Common definition of system calls
//
// Included using #[path] from Kernel/Core/syscalls/mod.rs and Userland/libtifflin_syscalls/src/lib.rs

pub const GRP_OFS: usize = 16;

macro_rules! expand_expr { ($e:expr) => {$e}; }
macro_rules! def_grp {
	($val:tt: $name:ident = { $( $v:tt: $n:ident, )* }) => {
		pub const $name: u32 = expand_expr!($val);
		$( pub const $n: u32 = ($name << GRP_OFS) | expand_expr!($v); )*
	}
}
macro_rules! def_class {
	($val:tt: $name:ident = { $( $v:tt: $n:ident, )* }, { $( $ev:tt: $en:ident, )* }) => {
		$( pub const $n: u16 = expand_expr!($v); )*
		$( pub const $en: u32 = 1 << expand_expr!($ev); )*
	}
}

def_grp!( 0: GROUP_CORE = {
	0: CORE_LOGWRITE,
	1: CORE_EXITPROCESS,
	2: CORE_EXITTHREAD,
	3: CORE_STARTPROCESS,
	4: CORE_STARTTHREAD,
	5: CORE_WAIT,
});

#[repr(C)]
#[derive(Debug)]
pub struct WaitItem {
	pub object: u32,
	pub flags: u32,
}

def_grp!( 1: GROUP_GUI = {
	0: GUI_NEWGROUP,
	1: GUI_NEWWINDOW,
});

def_grp!(2: GROUP_VFS = {
	0: VFS_OPENNODE,
	1: VFS_OPENFILE,
	2: VFS_OPENDIR,
});

def_grp!(3: GROUP_MEM = {
	0: MEM_ALLOCATE,
	1: MEM_REPROTECT,
	2: MEM_DEALLOCATE,
});

def_class!(0: CLAS_VFS_FILE = {
	0: VFS_FILE_READAT,
	1: VFS_FILE_WRITEAT,
	2: VFS_FILE_MEMMAP,
    },{
});
def_class!(1: CLASS_GUI_WIN = {
	0: GUI_WIN_SHOWHIDE,
	1: GUI_WIN_REDRAW,
	2: GUI_WIN_BLITRECT,
	2: GUI_WIN_FILLRECT,
    },{
    0: EV_GUI_WIN_INPUT,
});
<commit_msg>Syscalls - Rework macros to allow doc comments and checking of uniqueness<commit_after>// Tifflin OS Project
// - By John Hodge (thePowersGang)
//
// syscalls.inc.rs
// - Common definition of system calls
//
// Included using #[path] from Kernel/Core/syscalls/mod.rs and Userland/libtifflin_syscalls/src/lib.rs

pub const GRP_OFS: usize = 16;

macro_rules! expand_expr { ($e:expr) => {$e}; }

// Define a group of system calls
// TODO: Restructure like the class list
macro_rules! def_grp {
	($val:tt: $name:ident = { $( $(#[$a:meta])* =$v:tt: $n:ident, )* }) => {
		pub const $name: u32 = expand_expr!($val);
		$( $(#[$a])* pub const $n: u32 = ($name << GRP_OFS) | expand_expr!($v); )*
	}
}

def_grp!( 0: GROUP_CORE = {
	/// Write a logging message
	=0: CORE_LOGWRITE,
	=1: CORE_EXITPROCESS,
	=2: CORE_EXITTHREAD,
	=3: CORE_STARTPROCESS,
	=4: CORE_STARTTHREAD,
	=5: CORE_WAIT,
	=6: CORE_SENDMSG,
	=7: CORE_RECVMSG,
});

#[repr(C)]
#[derive(Debug)]
pub struct WaitItem {
	pub object: u32,
	pub flags: u32,
}

def_grp!( 1: GROUP_GUI = {
	/// Create a new GUI group/session (requires capability, init only usually)
	=0: GUI_NEWGROUP,
	/// Set the passed group object to be the controlling group for this process
	=1: GUI_BINDGROUP,
	/// Create a new window in the current group
	=2: GUI_NEWWINDOW,
});

def_grp!(2: GROUP_VFS = {
	=0: VFS_OPENNODE,
	=1: VFS_OPENFILE,
	=2: VFS_OPENDIR,
});

def_grp!(3: GROUP_MEM = {
	=0: MEM_ALLOCATE,
	=1: MEM_REPROTECT,
	=2: MEM_DEALLOCATE,
});

// Define all classes, using c-like enums to ensure that values are not duplicated
macro_rules! def_classes {
	( $($(#[$ca:meta])* =$cval:tt: $cname:ident = { $( $(#[$a:meta])* =$v:tt: $n:ident, )* }|{ $( $(#[$ea:meta])* =$ev:tt: $en:ident, )* }),* ) => {
		#[repr(u16)]
		enum Classes { $($cname = expand_expr!($cval)),* }
		mod calls { $(
			//#[repr(u16)]
			pub enum $cname { $($n = expand_expr!($v)),* }
		)* }
		mod masks { $(
			pub enum $cname { $($en = expand_expr!($ev)),* }
		)* }
		$( $(#[$ca])* pub const $cname: u16 = Classes::$cname as u16; )*
		$( $( $(#[$a])* pub const $n: u16 = self::calls::$cname::$n as u16; )* )*
		$( $( $(#[$ea])* pub const $en: u32 = 1 << self::masks::$cname::$en as usize; )* )*
		};
}

def_classes! {
	/// Handle to a spawned process, used to communicate with it
	=0: CLASS_PROCESS = {
		=0: CORE_PROCESS_KILL,
		=1: CORE_PROCESS_SENDOBJ,
		=2: CORE_PROCESS_SENDMSG,
	}|{
	},
	/// Opened file
	=1: CLASS_VFS_FILE = {
		=0: VFS_FILE_READAT,
		=1: VFS_FILE_WRITEAT,
		=2: VFS_FILE_MEMMAP,
	}|{
	},
	/// GUI Group/Session
	=2: CLASS_GUI_GROUP = {
		=0: GUI_GRP_FORCEACTIVE,
	}|{
		=0: EV_GUI_GRP_SHOWHIDE,
	},
	/// Window
	=3: CLASS_GUI_WIN = {
		=0: GUI_WIN_SHOWHIDE,
		=1: GUI_WIN_REDRAW,
		=2: GUI_WIN_BLITRECT,
		=3: GUI_WIN_FILLRECT,
	}|{
		=0: EV_GUI_WIN_INPUT,
	}
}
<|endoftext|>