<commit_before>// Copyright (c) 2020 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt};
use iml_rabbit::{
    basic_consume, connect_to_queue, connect_to_rabbit, purge_queue, BasicConsumeOptions,
    Connection, ImlRabbitError,
};
use iml_wire_types::{Fqdn, PluginMessage};

#[derive(Debug)]
pub enum ImlServiceQueueError {
    ImlRabbitError(ImlRabbitError),
    SerdeJsonError(serde_json::error::Error),
}

impl std::fmt::Display for ImlServiceQueueError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            ImlServiceQueueError::ImlRabbitError(ref err) => write!(f, "{}", err),
            ImlServiceQueueError::SerdeJsonError(ref err) => write!(f, "{}", err),
        }
    }
}

impl std::error::Error for ImlServiceQueueError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match *self {
            ImlServiceQueueError::ImlRabbitError(ref err) => Some(err),
            ImlServiceQueueError::SerdeJsonError(ref err) => Some(err),
        }
    }
}

impl From<ImlRabbitError> for ImlServiceQueueError {
    fn from(err: ImlRabbitError) -> Self {
        ImlServiceQueueError::ImlRabbitError(err)
    }
}

impl From<serde_json::error::Error> for ImlServiceQueueError {
    fn from(err: serde_json::error::Error) -> Self {
        ImlServiceQueueError::SerdeJsonError(err)
    }
}

/// Creates a consumer for an iml-service.
/// This fn will first purge the queue
/// and then consume from it.
///
/// This is expected to be called once during startup.
pub fn consume_service_queue(
    client: Connection,
    name: &'static str,
) -> impl Stream<Item = Result<PluginMessage, ImlServiceQueueError>> {
    let name2 = name.to_string();

    connect_to_queue(name.to_string(), client)
        .map_err(ImlServiceQueueError::from)
        .and_then(move |(c, q)| async {
            let c = purge_queue(c, name2).await?;

            Ok((c, q))
        })
        .and_then(move |(c, q)| {
            basic_consume(
                c,
                q,
                name,
                Some(BasicConsumeOptions {
                    no_ack: true,
                    ..BasicConsumeOptions::default()
                }),
            )
            .map_err(ImlServiceQueueError::from)
        })
        .map_ok(|s| s.map_err(ImlServiceQueueError::from))
        .try_flatten_stream()
        .and_then(|m| {
            tracing::debug!("Incoming message: {:?}", m.data);

            future::ready(serde_json::from_slice(&m.data).map_err(ImlServiceQueueError::from))
        })
        .boxed()
}

/// Given an incoming message Return an `Option` of fqdn and body
pub fn data_only(message: PluginMessage) -> Option<(Fqdn, serde_json::Value)> {
    match message {
        PluginMessage::Data { body, fqdn, .. } => Some((fqdn, body)),
        _ => None,
    }
}

pub fn into_deserialized<T: serde::de::DeserializeOwned>(
    (fqdn, body): (Fqdn, serde_json::Value),
) -> Result<(Fqdn, T), ImlServiceQueueError> {
    let v = serde_json::from_value(body)?;

    Ok((fqdn, v))
}

pub fn consume_data<T: serde::de::DeserializeOwned + Send + 'static>(
    queue_name: &'static str,
) -> impl Stream<Item = Result<(Fqdn, T), ImlServiceQueueError>> {
    connect_to_rabbit()
        .map_err(ImlServiceQueueError::from)
        .map_ok(move |client| consume_service_queue(client, queue_name))
        .try_flatten_stream()
        .try_filter_map(|x| future::ok(data_only(x)))
        .and_then(|x| future::ready(into_deserialized(x)))
        .boxed()
}
<commit_msg>Service Queue: print debug string instead of vec (#1874)<commit_after>// Copyright (c) 2020 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt};
use iml_rabbit::{
    basic_consume, connect_to_queue, connect_to_rabbit, purge_queue, BasicConsumeOptions,
    Connection, ImlRabbitError,
};
use iml_wire_types::{Fqdn, PluginMessage};

#[derive(Debug)]
pub enum ImlServiceQueueError {
    ImlRabbitError(ImlRabbitError),
    SerdeJsonError(serde_json::error::Error),
}

impl std::fmt::Display for ImlServiceQueueError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            ImlServiceQueueError::ImlRabbitError(ref err) => write!(f, "{}", err),
            ImlServiceQueueError::SerdeJsonError(ref err) => write!(f, "{}", err),
        }
    }
}

impl std::error::Error for ImlServiceQueueError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match *self {
            ImlServiceQueueError::ImlRabbitError(ref err) => Some(err),
            ImlServiceQueueError::SerdeJsonError(ref err) => Some(err),
        }
    }
}

impl From<ImlRabbitError> for ImlServiceQueueError {
    fn from(err: ImlRabbitError) -> Self {
        ImlServiceQueueError::ImlRabbitError(err)
    }
}

impl From<serde_json::error::Error> for ImlServiceQueueError {
    fn from(err: serde_json::error::Error) -> Self {
        ImlServiceQueueError::SerdeJsonError(err)
    }
}

/// Creates a consumer for an iml-service.
/// This fn will first purge the queue
/// and then consume from it.
///
/// This is expected to be called once during startup.
pub fn consume_service_queue(
    client: Connection,
    name: &'static str,
) -> impl Stream<Item = Result<PluginMessage, ImlServiceQueueError>> {
    let name2 = name.to_string();

    connect_to_queue(name.to_string(), client)
        .map_err(ImlServiceQueueError::from)
        .and_then(move |(c, q)| async {
            let c = purge_queue(c, name2).await?;

            Ok((c, q))
        })
        .and_then(move |(c, q)| {
            basic_consume(
                c,
                q,
                name,
                Some(BasicConsumeOptions {
                    no_ack: true,
                    ..BasicConsumeOptions::default()
                }),
            )
            .map_err(ImlServiceQueueError::from)
        })
        .map_ok(|s| s.map_err(ImlServiceQueueError::from))
        .try_flatten_stream()
        .and_then(|m| {
            tracing::debug!("Incoming message: {}", String::from_utf8_lossy(&m.data));

            future::ready(serde_json::from_slice(&m.data).map_err(ImlServiceQueueError::from))
        })
        .boxed()
}

/// Given an incoming message Return an `Option` of fqdn and body
pub fn data_only(message: PluginMessage) -> Option<(Fqdn, serde_json::Value)> {
    match message {
        PluginMessage::Data { body, fqdn, .. } => Some((fqdn, body)),
        _ => None,
    }
}

pub fn into_deserialized<T: serde::de::DeserializeOwned>(
    (fqdn, body): (Fqdn, serde_json::Value),
) -> Result<(Fqdn, T), ImlServiceQueueError> {
    let v = serde_json::from_value(body)?;

    Ok((fqdn, v))
}

pub fn consume_data<T: serde::de::DeserializeOwned + Send + 'static>(
    queue_name: &'static str,
) -> impl Stream<Item = Result<(Fqdn, T), ImlServiceQueueError>> {
    connect_to_rabbit()
        .map_err(ImlServiceQueueError::from)
        .map_ok(move |client| consume_service_queue(client, queue_name))
        .try_flatten_stream()
        .try_filter_map(|x| future::ok(data_only(x)))
        .and_then(|x| future::ready(into_deserialized(x)))
        .boxed()
}
<|endoftext|>


<commit_before>extern crate sdl;
extern crate libc;

use libc::uint8_t;
use libc::c_int;
use std::ptr::RawPtr;

pub struct IO_impl {
    keyboard_state: *uint8_t,
    size: c_int,
    key_set: [char, ..16]
}

fn index(keyset:[char, ..16], key:char) -> Option<u8> {
    for i in range(0u, keyset.len()) {
        if keyset[i] == key {
            Some(i);
    }
    }

    None
}

impl IO_impl {

    pub fn new(key_set: [char, ..16]) -> IO_impl {
        let a = 0;
        IO_impl { keyboard_state: unsafe {sdl::event::ll::SDL_GetKeyState(&a)},
                  key_set: key_set,
                  size :a }
    }

    pub fn get_key(&mut self) -> u8 {
        'key_loop : loop {
            match sdl::event::poll_event() {

            sdl::event::KeyEvent(k , _, _, _) =>  {
                match index(self.key_set, ((k as int) as u8) as char) {
                    Some(index) => { return index;},
                    None => {}
                };
            },

            _ => {}
            }
        }
    }

    pub fn key_pressed(&mut self, key:char) -> bool {
            unsafe {sdl::event::ll::SDL_PumpEvents(); /* Update keyboard state */
                    return *(self.keyboard_state.offset((key as u8) as int)) != 0;
            }
    }

}
<commit_msg>Fixed bug in which waiting for keypresses wern't being returned<commit_after>extern crate sdl;
extern crate libc;

use libc::uint8_t;
use libc::c_int;
use std::ptr::RawPtr;

pub struct IO_impl {
    keyboard_state: *uint8_t,
    size: c_int,
    key_set: [char, ..16]
}

fn index(keyset:[char, ..16], key:char) -> Option<u8> {
    for i in range(0u, keyset.len()) {
        if keyset[i] == key {
            return Some(i as u8);
    }
    }

    None
}

impl IO_impl {

    pub fn new(key_set: [char, ..16]) -> IO_impl {
        let a = 0;
        IO_impl { keyboard_state: unsafe {sdl::event::ll::SDL_GetKeyState(&a)},
                  key_set: key_set,
                  size :a }
    }

    pub fn get_key(&mut self) -> u8 {
        'key_loop : loop {
            match sdl::event::wait_event() {
            sdl::event::KeyEvent(k , _, _, _) =>  {
                match index(self.key_set, ((k as u8) as char)) {
                    Some(index) => { return index;},
                    None => {}
                };
            },

            _ => {}
            }
        }

    }

    pub fn key_pressed(&mut self, key:char) -> bool {
            unsafe {sdl::event::ll::SDL_PumpEvents(); /* Update keyboard state */
                    return *(self.keyboard_state.offset((key as u8) as int)) != 0;
            }
    }

}
<|endoftext|>


<commit_before>#![cfg(target_os = "android")]

extern crate android_glue;

use libc;
use std::sync::mpsc::{Receiver, channel};
use std::os::raw::c_void;
use {CreationError, Event, WindowEvent, MouseCursor};
use CreationError::OsError;
use WindowId as RootWindowId;
use events::{Touch, TouchPhase};
use window::MonitorId as RootMonitorId;

use std::collections::VecDeque;

use CursorState;
use WindowAttributes;

pub struct EventsLoop {
    event_rx: Receiver<android_glue::Event>,
}

#[derive(Clone)]
pub struct EventsLoopProxy;

impl EventsLoop {
    pub fn new() -> EventsLoop {
        let (tx, rx) = channel();
        android_glue::add_sender(tx);
        EventsLoop {
            event_rx: rx,
        }
    }

    #[inline]
    pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
        let mut rb = VecDeque::new();
        rb.push_back(MonitorId);
        rb
    }

    #[inline]
    pub fn get_primary_monitor(&self) -> MonitorId {
        MonitorId
    }

    pub fn poll_events<F>(&mut self, mut callback: F)
        where F: FnMut(::Event)
    {
        let event = match self.event_rx.try_recv() {
            Ok(android_glue::Event::EventMotion(motion)) => {
                Some(Event::WindowEvent {
                    window_id: RootWindowId(WindowId),
                    event: WindowEvent::Touch(Touch {
                        phase: match motion.action {
                            android_glue::MotionAction::Down => TouchPhase::Started,
                            android_glue::MotionAction::Move => TouchPhase::Moved,
                            android_glue::MotionAction::Up => TouchPhase::Ended,
                            android_glue::MotionAction::Cancel => TouchPhase::Cancelled,
                        },
                        location: (motion.x as f64, motion.y as f64),
                        id: motion.pointer_id as u64,
                        device_id: DEVICE_ID,
                    }),
                })
            },
            Ok(android_glue::Event::InitWindow) => {
                // The activity went to foreground.
                Some(Event::Suspended(false))
            },
            Ok(android_glue::Event::TermWindow) => {
                // The activity went to background.
                Some(Event::Suspended(true))
            },
            Ok(android_glue::Event::WindowResized) |
            Ok(android_glue::Event::ConfigChanged) => {
                // Activity Orientation changed or resized.
                let native_window = unsafe { android_glue::get_native_window() };
                if native_window.is_null() {
                    None
                } else {
                    let w = unsafe { ffi::ANativeWindow_getWidth(native_window as *const _) } as u32;
                    let h = unsafe { ffi::ANativeWindow_getHeight(native_window as *const _) } as u32;
                    Some(Event::WindowEvent {
                        window_id: RootWindowId(WindowId),
                        event: WindowEvent::Resized(w, h),
                    })
                }
            },
            Ok(android_glue::Event::WindowRedrawNeeded) => {
                // The activity needs to be redrawn.
                Some(Event::WindowEvent {
                    window_id: RootWindowId(WindowId),
                    event: WindowEvent::Refresh,
                })
            }
            _ => {
                None
            }
        };

        if let Some(event) = event {
            callback(event);
        }
    }

    pub fn run_forever<F>(&mut self, mut callback: F)
        where F: FnMut(::Event) -> ::ControlFlow,
    {
        // Yeah that's a very bad implementation.
        loop {
            let mut control_flow = ::ControlFlow::Continue;
            self.poll_events(|e| {
                if let ::ControlFlow::Break = callback(e) {
                    control_flow = ::ControlFlow::Break;
                }
            });
            if let ::ControlFlow::Break = control_flow {
                break;
            }
            ::std::thread::sleep(::std::time::Duration::from_millis(5));
        }
    }

    pub fn create_proxy(&self) -> EventsLoopProxy {
        EventsLoopProxy
    }
}

impl EventsLoopProxy {
    pub fn wakeup(&self) -> Result<(), ::EventsLoopClosed> {
        android_glue::wake_event_loop();
        Ok(())
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId;

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId;

pub struct Window {
    native_window: *const c_void,
}

#[derive(Clone)]
pub struct MonitorId;

mod ffi;

impl MonitorId {
    #[inline]
    pub fn get_name(&self) -> Option<String> {
        Some("Primary".to_string())
    }

    #[inline]
    pub fn get_dimensions(&self) -> (u32, u32) {
        unimplemented!()
    }

    #[inline]
    pub fn get_position(&self) -> (i32, i32) {
        // Android assumes single screen
        (0, 0)
    }

    #[inline]
    pub fn get_hidpi_factor(&self) -> f32 {
        1.0
    }
}

#[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes;
#[derive(Clone, Default)]
pub struct PlatformSpecificHeadlessBuilderAttributes;

impl Window {
    pub fn new(_: &EventsLoop, win_attribs: &WindowAttributes,
               _: &PlatformSpecificWindowBuilderAttributes)
               -> Result<Window, CreationError>
    {
        // not implemented
        assert!(win_attribs.min_dimensions.is_none());
        assert!(win_attribs.max_dimensions.is_none());

        let native_window = unsafe { android_glue::get_native_window() };
        if native_window.is_null() {
            return Err(OsError(format!("Android's native window is null")));
        }

        android_glue::set_multitouch(win_attribs.multitouch);

        Ok(Window {
            native_window: native_window as *const _,
        })
    }

    #[inline]
    pub fn get_native_window(&self) -> *const c_void {
        self.native_window
    }

    #[inline]
    pub fn set_title(&self, _: &str) {
    }

    #[inline]
    pub fn show(&self) {
    }

    #[inline]
    pub fn hide(&self) {
    }

    #[inline]
    pub fn get_position(&self) -> Option<(i32, i32)> {
        None
    }

    #[inline]
    pub fn set_position(&self, _x: i32, _y: i32) {
    }

    #[inline]
    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        if self.native_window.is_null() {
            None
        } else {
            Some((
                unsafe { ffi::ANativeWindow_getWidth(self.native_window as *const _) } as u32,
                unsafe { ffi::ANativeWindow_getHeight(self.native_window as *const _) } as u32
            ))
        }
    }

    #[inline]
    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        self.get_inner_size()
    }

    #[inline]
    pub fn set_inner_size(&self, _x: u32, _y: u32) {
    }

    #[inline]
    pub fn platform_display(&self) -> *mut libc::c_void {
        unimplemented!();
    }

    #[inline]
    pub fn platform_window(&self) -> *mut libc::c_void {
        unimplemented!()
    }

    #[inline]
    pub fn set_cursor(&self, _: MouseCursor) {
    }

    #[inline]
    pub fn set_cursor_state(&self, _state: CursorState) -> Result<(), String> {
        Ok(())
    }

    #[inline]
    pub fn hidpi_factor(&self) -> f32 {
        1.0
    }

    #[inline]
    pub fn set_cursor_position(&self, _x: i32, _y: i32) -> Result<(), ()> {
        Ok(())
    }

    #[inline]
    pub fn set_maximized(&self, _maximized: bool) {
        // Android has single screen maximized apps so nothing to do
    }

    #[inline]
    pub fn set_fullscreen(&self, _monitor: Option<RootMonitorId>) {
        // Android has single screen maximized apps so nothing to do
    }

    #[inline]
    pub fn get_current_monitor(&self) -> RootMonitorId {
        RootMonitorId{inner: MonitorId}
    }

    pub fn id(&self) -> WindowId {
        WindowId
    }
}

unsafe impl Send for Window {}
unsafe impl Sync for Window {}

// Constant device ID, to be removed when this backend is updated to report real device IDs.
const DEVICE_ID: ::DeviceId = ::DeviceId(DeviceId);
<commit_msg>Made poll events loop over as many events as there may be instead of just one. (#333)<commit_after>#![cfg(target_os = "android")]

extern crate android_glue;

use libc;
use std::sync::mpsc::{Receiver, channel};
use std::os::raw::c_void;
use {CreationError, Event, WindowEvent, MouseCursor};
use CreationError::OsError;
use WindowId as RootWindowId;
use events::{Touch, TouchPhase};
use window::MonitorId as RootMonitorId;

use std::collections::VecDeque;

use CursorState;
use WindowAttributes;

pub struct EventsLoop {
    event_rx: Receiver<android_glue::Event>,
}

#[derive(Clone)]
pub struct EventsLoopProxy;

impl EventsLoop {
    pub fn new() -> EventsLoop {
        let (tx, rx) = channel();
        android_glue::add_sender(tx);
        EventsLoop {
            event_rx: rx,
        }
    }

    #[inline]
    pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
        let mut rb = VecDeque::new();
        rb.push_back(MonitorId);
        rb
    }

    #[inline]
    pub fn get_primary_monitor(&self) -> MonitorId {
        MonitorId
    }

    pub fn poll_events<F>(&mut self, mut callback: F)
        where F: FnMut(::Event)
    {
        while let Ok(event) = self.event_rx.try_recv() {

            let e = match event{
                android_glue::Event::EventMotion(motion) => {
                    Some(Event::WindowEvent {
                        window_id: RootWindowId(WindowId),
                        event: WindowEvent::Touch(Touch {
                            phase: match motion.action {
                                android_glue::MotionAction::Down => TouchPhase::Started,
                                android_glue::MotionAction::Move => TouchPhase::Moved,
                                android_glue::MotionAction::Up => TouchPhase::Ended,
                                android_glue::MotionAction::Cancel => TouchPhase::Cancelled,
                            },
                            location: (motion.x as f64, motion.y as f64),
                            id: motion.pointer_id as u64,
                            device_id: DEVICE_ID,
                        }),
                    })
                },
                android_glue::Event::InitWindow => {
                    // The activity went to foreground.
                    Some(Event::Suspended(false))
                },
                android_glue::Event::TermWindow => {
                    // The activity went to background.
                    Some(Event::Suspended(true))
                },
                android_glue::Event::WindowResized |
                android_glue::Event::ConfigChanged => {
                    // Activity Orientation changed or resized.
                    let native_window = unsafe { android_glue::get_native_window() };
                    if native_window.is_null() {
                        None
                    } else {
                        let w = unsafe { ffi::ANativeWindow_getWidth(native_window as *const _) } as u32;
                        let h = unsafe { ffi::ANativeWindow_getHeight(native_window as *const _) } as u32;
                        Some(Event::WindowEvent {
                            window_id: RootWindowId(WindowId),
                            event: WindowEvent::Resized(w, h),
                        })
                    }
                },
                android_glue::Event::WindowRedrawNeeded => {
                    // The activity needs to be redrawn.
                    Some(Event::WindowEvent {
                        window_id: RootWindowId(WindowId),
                        event: WindowEvent::Refresh,
                    })
                }
                _ => {
                    None
                }
            };

            if let Some(event) = e {
                callback(event);
            }
        };
    }

    pub fn run_forever<F>(&mut self, mut callback: F)
        where F: FnMut(::Event) -> ::ControlFlow,
    {
        // Yeah that's a very bad implementation.
        loop {
            let mut control_flow = ::ControlFlow::Continue;
            self.poll_events(|e| {
                if let ::ControlFlow::Break = callback(e) {
                    control_flow = ::ControlFlow::Break;
                }
            });
            if let ::ControlFlow::Break = control_flow {
                break;
            }
            ::std::thread::sleep(::std::time::Duration::from_millis(5));
        }
    }

    pub fn create_proxy(&self) -> EventsLoopProxy {
        EventsLoopProxy
    }
}

impl EventsLoopProxy {
    pub fn wakeup(&self) -> Result<(), ::EventsLoopClosed> {
        android_glue::wake_event_loop();
        Ok(())
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId;

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId;

pub struct Window {
    native_window: *const c_void,
}

#[derive(Clone)]
pub struct MonitorId;

mod ffi;

impl MonitorId {
    #[inline]
    pub fn get_name(&self) -> Option<String> {
        Some("Primary".to_string())
    }

    #[inline]
    pub fn get_dimensions(&self) -> (u32, u32) {
        unimplemented!()
    }

    #[inline]
    pub fn get_position(&self) -> (i32, i32) {
        // Android assumes single screen
        (0, 0)
    }

    #[inline]
    pub fn get_hidpi_factor(&self) -> f32 {
        1.0
    }
}

#[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes;
#[derive(Clone, Default)]
pub struct PlatformSpecificHeadlessBuilderAttributes;

impl Window {
    pub fn new(_: &EventsLoop, win_attribs: &WindowAttributes,
               _: &PlatformSpecificWindowBuilderAttributes)
               -> Result<Window, CreationError>
    {
        // not implemented
        assert!(win_attribs.min_dimensions.is_none());
        assert!(win_attribs.max_dimensions.is_none());

        let native_window = unsafe { android_glue::get_native_window() };
        if native_window.is_null() {
            return Err(OsError(format!("Android's native window is null")));
        }

        android_glue::set_multitouch(win_attribs.multitouch);

        Ok(Window {
            native_window: native_window as *const _,
        })
    }

    #[inline]
    pub fn get_native_window(&self) -> *const c_void {
        self.native_window
    }

    #[inline]
    pub fn set_title(&self, _: &str) {
    }

    #[inline]
    pub fn show(&self) {
    }

    #[inline]
    pub fn hide(&self) {
    }

    #[inline]
    pub fn get_position(&self) -> Option<(i32, i32)> {
        None
    }

    #[inline]
    pub fn set_position(&self, _x: i32, _y: i32) {
    }

    #[inline]
    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        if self.native_window.is_null() {
            None
        } else {
            Some((
                unsafe { ffi::ANativeWindow_getWidth(self.native_window as *const _) } as u32,
                unsafe { ffi::ANativeWindow_getHeight(self.native_window as *const _) } as u32
            ))
        }
    }

    #[inline]
    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        self.get_inner_size()
    }

    #[inline]
    pub fn set_inner_size(&self, _x: u32, _y: u32) {
    }

    #[inline]
    pub fn platform_display(&self) -> *mut libc::c_void {
        unimplemented!();
    }

    #[inline]
    pub fn platform_window(&self) -> *mut libc::c_void {
        unimplemented!()
    }

    #[inline]
    pub fn set_cursor(&self, _: MouseCursor) {
    }

    #[inline]
    pub fn set_cursor_state(&self, _state: CursorState) -> Result<(), String> {
        Ok(())
    }

    #[inline]
    pub fn hidpi_factor(&self) -> f32 {
        1.0
    }

    #[inline]
    pub fn set_cursor_position(&self, _x: i32, _y: i32) -> Result<(), ()> {
        Ok(())
    }

    #[inline]
    pub fn set_maximized(&self, _maximized: bool) {
        // Android has single screen maximized apps so nothing to do
    }

    #[inline]
    pub fn set_fullscreen(&self, _monitor: Option<RootMonitorId>) {
        // Android has single screen maximized apps so nothing to do
    }

    #[inline]
    pub fn get_current_monitor(&self) -> RootMonitorId {
        RootMonitorId{inner: MonitorId}
    }

    pub fn id(&self) -> WindowId {
        WindowId
    }
}

unsafe impl Send for Window {}
unsafe impl Sync for Window {}

// Constant device ID, to be removed when this backend is updated to report real device IDs.
const DEVICE_ID: ::DeviceId = ::DeviceId(DeviceId);
<|endoftext|>


<commit_before>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2013, 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#![crate_name = "grust-Gio-2_0"]

#![crate_type = "lib"]

extern crate grust;
extern crate "grust-GLib-2_0" as glib;
extern crate "grust-GObject-2_0" as gobject;
extern crate libc;

use grust::gtype::GType;
use grust::marker;
use grust::object;
use grust::refcount;
use grust::types;
use grust::utf8;

use cast::AsyncResult as _cast_AsyncResult;
use cast::Cancellable as _cast_Cancellable;

#[repr(C)]
pub struct AsyncResult {
    marker: marker::ObjectMarker
}

#[repr(C)]
pub struct File {
    marker: marker::ObjectMarker
}

#[repr(C)]
pub struct Cancellable {
    parent_instance: gobject::Object,
    _priv: types::gpointer
}

#[repr(C)]
pub struct InputStream {
    parent_instance: gobject::Object,
    _priv: types::gpointer
}

#[repr(C)]
pub struct FileInputStream {
    parent_instance: InputStream,
    _priv: types::gpointer
}

pub mod enums {

    pub mod io_error {

        use grust::error;
        use grust::quark;
        use std::fmt;
        use std::sync::atomic;

        #[deriving(FromPrimitive,PartialEq,Eq)]
        #[repr(C)]
        pub enum IOErrorEnum {
            Failed = 0,
            NotFound = 1,
            Exists = 2,
            // ...
        }

        impl fmt::Show for IOErrorEnum {
            fn fmt(&self, format: &mut fmt::Formatter) -> fmt::Result {
                let s: &'static str = match *self {
                    IOErrorEnum::Failed   => "failed",
                    IOErrorEnum::NotFound => "not-found",
                    IOErrorEnum::Exists   => "exists",
                    // ...
                };
                s.fmt(format)
            }
        }

        static mut ERROR_QUARK: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT;

        impl error::ErrorDomain for IOErrorEnum {
            fn error_domain(_: Option<IOErrorEnum>) -> quark::Quark {
                unsafe {
                    let mut d = ERROR_QUARK.load(atomic::Relaxed)
                                as quark::Quark;
                    if d == 0 {
                        d = quark::from_static_string("g-io-error-quark\0");
                        ERROR_QUARK.store(d as uint, atomic::Relaxed);
                    }
                    d
                }
            }
        }

        impl ToPrimitive for IOErrorEnum {
            fn to_int(&self) -> Option<int> { Some(*self as int) }
            fn to_i64(&self) -> Option<i64> { Some(*self as i64) }
            fn to_u64(&self) -> Option<u64> { Some(*self as u64) }
        }
    }
}

#[allow(improper_ctypes)]
pub mod raw {
    use grust::types::{gchar,gint,gpointer};
    use grust::gtype::GType;
    use grust::error::raw::GError;
    use gobject;
    use libc;

    pub type GAsyncResult = super::AsyncResult;
    pub type GFile = super::File;
    pub type GCancellable = super::Cancellable;
    pub type GInputStream = super::InputStream;
    pub type GFileInputStream = super::FileInputStream;

    pub type GAsyncReadyCallback = extern "C" fn(source_object: *mut gobject::raw::GObject,
                                                 res: *mut GAsyncResult,
                                                 user_data: gpointer);

    #[link(name="gio-2.0")]
    extern {
        pub fn g_async_result_get_type() -> GType;
        pub fn g_file_get_type() -> GType;
        pub fn g_file_new_for_path(path: *const gchar) -> *mut GFile;
        pub fn g_file_get_path(file: *mut GFile) -> *mut libc::c_char;
        pub fn g_file_read_async(file: *mut GFile,
                                 io_priority: gint,
                                 cancellable: *mut GCancellable,
                                 callback: GAsyncReadyCallback,
                                 user_data: gpointer);
        pub fn g_file_read_finish(file: *mut GFile,
                                  res: *mut GAsyncResult,
                                  error: *mut *mut GError)
                                  -> *mut GFileInputStream;
    }
}

pub mod async {

    use gobject;

    pub type AsyncReadyCallback =
                for<'a> proc(&'a mut gobject::Object,
                             &'a mut super::AsyncResult)
                            : Send;
}

mod async_shim {

    use grust::types;
    use super::async;
    use super::raw;
    use gobject;
    use std::mem;

    pub extern "C" fn async_ready_callback(source_object: *mut gobject::raw::GObject,
                                           res: *mut raw::GAsyncResult,
                                           user_data: types::gpointer) {
        unsafe {
            let callback: Box<async::AsyncReadyCallback> =
                    mem::transmute(user_data);

            (*callback)(&mut *source_object, &mut *res);
        }
    }
}

pub mod cast {

    use gobject;

    pub trait AsyncResult {
        fn as_gio_async_result<'a>(&'a self) -> &'a super::AsyncResult;
        fn as_mut_gio_async_result<'a>(&'a mut self) -> &'a mut super::AsyncResult;
    }

    pub trait Cancellable : gobject::cast::Object {
        fn as_gio_cancellable<'a>(&'a self) -> &'a super::Cancellable;
        fn as_mut_gio_cancellable<'a>(&'a mut self) -> &'a mut super::Cancellable;
    }

    pub trait InputStream : gobject::cast::Object {
    }

    pub trait FileInputStream : InputStream {
    }

    pub trait File {
        fn as_gio_file<'a>(&'a self) -> &'a super::File;
        fn as_mut_gio_file<'a>(&'a mut self) -> &'a mut super::File;
    }
}

impl File {

    pub fn new_for_path<T: utf8::ToUTF8>(path: T) -> refcount::Ref<File> {
        let ret = path.with_utf8_c_str(|p| {
            unsafe {
                raw::g_file_new_for_path(p)
            }
        });
        unsafe { refcount::raw::ref_from_ptr(ret) }
    }

    pub fn get_path<'a>(&mut self) -> utf8::UTF8Buf {
        unsafe {
            let ret = raw::g_file_get_path(self);
            utf8::UTF8Buf::wrap(ret)
        }
    }

    pub fn read_async(&mut self,
                      io_priority: types::gint,
                      cancellable: Option<&mut Cancellable>,
                      callback: Box<async::AsyncReadyCallback>) {
        unsafe {
            let raw_cancellable =
                match cancellable {
                    Some(c) => c.as_mut_gio_cancellable() as *mut raw::GCancellable,
                    None    => std::ptr::null_mut::<raw::GCancellable>()
                };
            let raw_callback: types::gpointer = std::mem::transmute(callback);

            raw::g_file_read_async(self,
                                   io_priority as libc::c_int,
                                   raw_cancellable,
                                   async_shim::async_ready_callback,
                                   raw_callback);
        }
    }

    pub fn read_finish(&mut self, res: &mut AsyncResult)
                      -> std::result::Result<refcount::Ref<FileInputStream>,
                                             grust::error::Error> {
        unsafe {
            let mut err: grust::error::Error = grust::error::unset();
            let ret = raw::g_file_read_finish(self,
                                              res.as_mut_gio_async_result(),
                                              err.slot_ptr());
            if err.is_set() {
                std::result::Err(err)
            } else {
                std::result::Ok(refcount::raw::ref_from_ptr(ret))
            }
        }
    }
}

impl object::ObjectType for AsyncResult {
    fn get_type(&self) -> GType {
        unsafe {
            raw::g_async_result_get_type()
        }
    }
}

impl object::ObjectType for File {
    fn get_type(&self) -> GType {
        unsafe {
            raw::g_file_get_type()
        }
    }
}

impl refcount::Refcount for File {
    fn refcount_funcs(&self) -> &'static refcount::RefcountFuncs {
        &object::REFCOUNT_FUNCS
    }
}

impl refcount::Refcount for FileInputStream {
    fn refcount_funcs(&self) -> &'static refcount::RefcountFuncs {
        &object::REFCOUNT_FUNCS
    }
}

impl cast::AsyncResult for AsyncResult {
    fn as_gio_async_result<'a>(&'a self) -> &'a AsyncResult { self }
    fn as_mut_gio_async_result<'a>(&'a mut self) -> &'a mut AsyncResult { self }
}

impl gobject::cast::Object for Cancellable {
    fn as_gobject_object<'a>(&'a self) -> &'a gobject::Object {
        &self.parent_instance
    }
    fn as_mut_gobject_object<'a>(&'a mut self) -> &'a mut gobject::Object {
        &mut self.parent_instance
    }
}

impl cast::Cancellable for Cancellable {
    fn as_gio_cancellable<'a>(&'a self) -> &'a Cancellable { self }
    fn as_mut_gio_cancellable<'a>(&'a mut self) -> &'a mut Cancellable { self }
}

impl cast::File for File {
    fn as_gio_file<'a>(&'a self) -> &'a File { self }
    fn as_mut_gio_file<'a>(&'a mut self) -> &'a mut File { self }
}

impl gobject::cast::Object for InputStream {
    fn as_gobject_object<'a>(&'a self) -> &'a gobject::Object {
        &self.parent_instance
    }
    fn as_mut_gobject_object<'a>(&'a mut self) -> &'a mut gobject::Object {
        &mut self.parent_instance
    }
}

impl gobject::cast::Object for FileInputStream {
    fn as_gobject_object<'a>(&'a self) -> &'a gobject::Object {
        self.parent_instance.as_gobject_object()
    }
    fn as_mut_gobject_object<'a>(&'a mut self) -> &'a mut gobject::Object {
        self.parent_instance.as_mut_gobject_object()
    }
}
<commit_msg>Bring the generated enum to crate's top-level namespace<commit_after>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2013, 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#![crate_name = "grust-Gio-2_0"]

#![crate_type = "lib"]

extern crate grust;
extern crate "grust-GLib-2_0" as glib;
extern crate "grust-GObject-2_0" as gobject;
extern crate libc;

use grust::error;
use grust::gtype::GType;
use grust::marker;
use grust::object;
use grust::quark;
use grust::refcount;
use grust::types;
use grust::utf8;

use cast::AsyncResult as _cast_AsyncResult;
use cast::Cancellable as _cast_Cancellable;

use std::fmt;
use std::sync::atomic;

#[repr(C)]
pub struct AsyncResult {
    marker: marker::ObjectMarker
}

#[repr(C)]
pub struct File {
    marker: marker::ObjectMarker
}

#[repr(C)]
pub struct Cancellable {
    parent_instance: gobject::Object,
    _priv: types::gpointer
}

#[repr(C)]
pub struct InputStream {
    parent_instance: gobject::Object,
    _priv: types::gpointer
}

#[repr(C)]
pub struct FileInputStream {
    parent_instance: InputStream,
    _priv: types::gpointer
}

#[deriving(FromPrimitive,PartialEq,Eq)]
#[repr(C)]
pub enum IOErrorEnum {
    Failed = 0,
    NotFound = 1,
    Exists = 2,
    // ...
}

impl fmt::Show for IOErrorEnum {
    fn fmt(&self, format: &mut fmt::Formatter) -> fmt::Result {
        let s: &'static str = match *self {
            IOErrorEnum::Failed   => "failed",
            IOErrorEnum::NotFound => "not-found",
            IOErrorEnum::Exists   => "exists",
            // ...
        };
        s.fmt(format)
    }
}

static mut ERROR_QUARK: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT;

impl error::ErrorDomain for IOErrorEnum {
    fn error_domain(_: Option<IOErrorEnum>) -> quark::Quark {
        unsafe {
            let mut d = ERROR_QUARK.load(atomic::Relaxed)
                        as quark::Quark;
            if d == 0 {
                d = quark::from_static_string("g-io-error-quark\0");
                ERROR_QUARK.store(d as uint, atomic::Relaxed);
            }
            d
        }
    }
}

impl ToPrimitive for IOErrorEnum {
    fn to_int(&self) -> Option<int> { Some(*self as int) }
    fn to_i64(&self) -> Option<i64> { Some(*self as i64) }
    fn to_u64(&self) -> Option<u64> { Some(*self as u64) }
}

#[allow(improper_ctypes)]
pub mod raw {
    use grust::types::{gchar,gint,gpointer};
    use grust::gtype::GType;
    use grust::error::raw::GError;
    use gobject;
    use libc;

    pub type GAsyncResult = super::AsyncResult;
    pub type GFile = super::File;
    pub type GCancellable = super::Cancellable;
    pub type GInputStream = super::InputStream;
    pub type GFileInputStream = super::FileInputStream;

    pub type GAsyncReadyCallback = extern "C" fn(source_object: *mut gobject::raw::GObject,
                                                 res: *mut GAsyncResult,
                                                 user_data: gpointer);

    #[link(name="gio-2.0")]
    extern {
        pub fn g_async_result_get_type() -> GType;
        pub fn g_file_get_type() -> GType;
        pub fn g_file_new_for_path(path: *const gchar) -> *mut GFile;
        pub fn g_file_get_path(file: *mut GFile) -> *mut libc::c_char;
        pub fn g_file_read_async(file: *mut GFile,
                                 io_priority: gint,
                                 cancellable: *mut GCancellable,
                                 callback: GAsyncReadyCallback,
                                 user_data: gpointer);
        pub fn g_file_read_finish(file: *mut GFile,
                                  res: *mut GAsyncResult,
                                  error: *mut *mut GError)
                                  -> *mut GFileInputStream;
    }
}

pub mod async {

    use gobject;

    pub type AsyncReadyCallback =
                for<'a> proc(&'a mut gobject::Object,
                             &'a mut super::AsyncResult)
                            : Send;
}

mod async_shim {

    use grust::types;
    use super::async;
    use super::raw;
    use gobject;
    use std::mem;

    pub extern "C" fn async_ready_callback(source_object: *mut gobject::raw::GObject,
                                           res: *mut raw::GAsyncResult,
                                           user_data: types::gpointer) {
        unsafe {
            let callback: Box<async::AsyncReadyCallback> =
                    mem::transmute(user_data);

            (*callback)(&mut *source_object, &mut *res);
        }
    }
}

pub mod cast {

    use gobject;

    pub trait AsyncResult {
        fn as_gio_async_result<'a>(&'a self) -> &'a super::AsyncResult;
        fn as_mut_gio_async_result<'a>(&'a mut self) -> &'a mut super::AsyncResult;
    }

    pub trait Cancellable : gobject::cast::Object {
        fn as_gio_cancellable<'a>(&'a self) -> &'a super::Cancellable;
        fn as_mut_gio_cancellable<'a>(&'a mut self) -> &'a mut super::Cancellable;
    }

    pub trait InputStream : gobject::cast::Object {
    }

    pub trait FileInputStream : InputStream {
    }

    pub trait File {
        fn as_gio_file<'a>(&'a self) -> &'a super::File;
        fn as_mut_gio_file<'a>(&'a mut self) -> &'a mut super::File;
    }
}

impl File {

    pub fn new_for_path<T: utf8::ToUTF8>(path: T) -> refcount::Ref<File> {
        let ret = path.with_utf8_c_str(|p| {
            unsafe {
                raw::g_file_new_for_path(p)
            }
        });
        unsafe { refcount::raw::ref_from_ptr(ret) }
    }

    pub fn get_path<'a>(&mut self) -> utf8::UTF8Buf {
        unsafe {
            let ret = raw::g_file_get_path(self);
            utf8::UTF8Buf::wrap(ret)
        }
    }

    pub fn read_async(&mut self,
                      io_priority: types::gint,
                      cancellable: Option<&mut Cancellable>,
                      callback: Box<async::AsyncReadyCallback>) {
        unsafe {
            let raw_cancellable =
                match cancellable {
                    Some(c) => c.as_mut_gio_cancellable() as *mut raw::GCancellable,
                    None    => std::ptr::null_mut::<raw::GCancellable>()
                };
            let raw_callback: types::gpointer = std::mem::transmute(callback);

            raw::g_file_read_async(self,
                                   io_priority as libc::c_int,
                                   raw_cancellable,
                                   async_shim::async_ready_callback,
                                   raw_callback);
        }
    }

    pub fn read_finish(&mut self, res: &mut AsyncResult)
                      -> std::result::Result<refcount::Ref<FileInputStream>,
                                             grust::error::Error> {
        unsafe {
            let mut err: grust::error::Error = grust::error::unset();
            let ret = raw::g_file_read_finish(self,
                                              res.as_mut_gio_async_result(),
                                              err.slot_ptr());
            if err.is_set() {
                std::result::Err(err)
            } else {
                std::result::Ok(refcount::raw::ref_from_ptr(ret))
            }
        }
    }
}

impl object::ObjectType for AsyncResult {
    fn get_type(&self) -> GType {
        unsafe {
            raw::g_async_result_get_type()
        }
    }
}

impl object::ObjectType for File {
    fn get_type(&self) -> GType {
        unsafe {
            raw::g_file_get_type()
        }
    }
}

impl refcount::Refcount for File {
    fn refcount_funcs(&self) -> &'static refcount::RefcountFuncs {
        &object::REFCOUNT_FUNCS
    }
}

impl refcount::Refcount for FileInputStream {
    fn refcount_funcs(&self) -> &'static refcount::RefcountFuncs {
        &object::REFCOUNT_FUNCS
    }
}

impl cast::AsyncResult for AsyncResult {
    fn as_gio_async_result<'a>(&'a self) -> &'a AsyncResult { self }
    fn as_mut_gio_async_result<'a>(&'a mut self) -> &'a mut AsyncResult { self }
}

impl gobject::cast::Object for Cancellable {
    fn as_gobject_object<'a>(&'a self) -> &'a gobject::Object {
        &self.parent_instance
    }
    fn as_mut_gobject_object<'a>(&'a mut self) -> &'a mut gobject::Object {
        &mut self.parent_instance
    }
}

impl cast::Cancellable for Cancellable {
    fn as_gio_cancellable<'a>(&'a self) -> &'a Cancellable { self }
    fn as_mut_gio_cancellable<'a>(&'a mut self) -> &'a mut Cancellable { self }
}

impl cast::File for File {
    fn as_gio_file<'a>(&'a self) -> &'a File { self }
    fn as_mut_gio_file<'a>(&'a mut self) -> &'a mut File { self }
}

impl gobject::cast::Object for InputStream {
    fn as_gobject_object<'a>(&'a self) -> &'a gobject::Object {
        &self.parent_instance
    }
    fn as_mut_gobject_object<'a>(&'a mut self) -> &'a mut gobject::Object {
        &mut self.parent_instance
    }
}

impl gobject::cast::Object for FileInputStream {
    fn as_gobject_object<'a>(&'a self) -> &'a gobject::Object {
        self.parent_instance.as_gobject_object()
    }
    fn as_mut_gobject_object<'a>(&'a mut self) -> &'a mut gobject::Object {
        self.parent_instance.as_mut_gobject_object()
    }
}
<|endoftext|>


<commit_before>//#[cfg(test)] use racer::testutils::{rejustify, slice};

pub fn rejustify(src: &str) -> String {
    let s = &src[1..]; // remove the newline
    let mut sb = String::new();
    for l in s.lines() {
        let tabless = &l[4..];
        sb.push_str(tabless);
        if tabless.len() != 0 {
            sb.push_str("\n");
        }
    }
    let newlen = sb.len()-1; // remove the trailing newline
    sb.truncate(newlen);
    sb
}

pub fn slice(src: &str, (begin, end): (usize, usize)) -> &str{
    &src[begin..end]
}

enum State {
    StateCode,
    StateComment,
    StateCommentBlock,
    StateString,
    StateFinished
}

pub struct CodeIndicesIter<'a> {
    src: &'a str,
    pos: usize,
    state: State
}

impl<'a> Iterator for CodeIndicesIter<'a> {
    type Item = (usize, usize);

    #[inline]
    fn next(&mut self) -> Option<(usize, usize)> {
        let res = match self.state {
            State::StateCode => Some(code(self)),
            State::StateComment => Some(comment(self)),
            State::StateCommentBlock  => Some(comment_block(self)),
            State::StateString => Some(string(self)),
            State::StateFinished => None
        };
        res
    }
}

fn code(self_: &mut CodeIndicesIter) -> (usize,usize) {

    let start = match self_.state {
        State::StateString => { self_.pos-1 }, // include dblquotes
        _ => { self_.pos }
    };
    let src_bytes = self_.src.as_bytes();
    for &b in src_bytes[self_.pos..].iter(){
        self_.pos += 1;
        match b {
            b'/' => match src_bytes[self_.pos] {
                b'/' => {
                    self_.state = State::StateComment;
                    self_.pos +=1;
                    return (start, self_.pos-2);
                },
                b'*' => {
                    self_.state = State::StateCommentBlock;
                    self_.pos +=1;
                    return (start, self_.pos-2);
                },
                _ => {}
            },
            b'"' => {
                self_.state = State::StateString;
                return (start, self_.pos); // include dblquotes
            },
            _ => {}
        }
    }

    self_.state = State::StateFinished;
    (start, self_.src.len())
}

fn comment(self_: &mut CodeIndicesIter) -> (usize,usize) {
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        if b == b'\n' { break; }
    }
    code(self_)
}

fn comment_block(self_: &mut CodeIndicesIter) -> (usize,usize) {

    let mut nesting_level = 0u16; // should be enough
    let mut prev = b' ';
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        match b {
            b'/' if prev == b'*' => {
                if nesting_level == 0 {
                    break;
                } else {
                    nesting_level -= 1;
                }
            },
            b'*' if prev == b'/' => {
                nesting_level += 1;
            },
            _ => { prev = b; }
        }
    }
    code(self_)
}

fn string(self_: &mut CodeIndicesIter) -> (usize,usize) {
    let mut is_not_escaped = true;
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        match b {
            b'"' if is_not_escaped  => { break; },
            b'\\' => { is_not_escaped = !is_not_escaped; },
            _ => { is_not_escaped = true; }
        }
    }
    code(self_)
}

/// Returns indices of chunks of code (minus comments and string contents)
pub fn code_chunks<'a>(src: &'a str) -> CodeIndicesIter<'a> {
    CodeIndicesIter { src: src, state: State::StateCode, pos: 0 }
}

#[test]
fn removes_a_comment() {
    let src = &rejustify("
    this is some code // this is a comment
    some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_contents() {
    let src = &rejustify("
    this is some code \"this is a string\" more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_contents_with_a_comment_in_it() {
    let src = &rejustify("
    this is some code \"string with a // fake comment \" more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_a_comment_with_a_dbl_quote_in_it() {
    let src = &rejustify("
    this is some code // comment with \" double quote
    some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_multiline_comment() {
    let src = &rejustify("
    this is some code /* this is a
    \"multiline\" comment */some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn handles_nesting_of_block_comments() {
    let src = &rejustify("
    this is some code /* nested /* block */ comment */ some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!(" some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_with_escaped_dblquote_in_it() {
    let src = &rejustify("
    this is some code \"string with a \\\" escaped dblquote fake comment \" more code
    ")[];

    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_with_escaped_slash_before_dblquote_in_it() {
    let src = &rejustify("
    this is some code \"string with an escaped slash, so dbl quote does end the string after all \\\\\" more code
    ")[];

    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn handles_tricky_bit_from_str_rs() {
    let src = &rejustify("
        before(\"\\\\\'\\\\\\\"\\\\\\\\\");
        more_code(\" skip me \")
    ")[];

    for (start,end) in code_chunks(src) {
        println!("BLOB |{}|",&src[start..end]);
        if (&src[start..end]).contains("skip me") {
            panic!("{}", &src[start..end]);
        }
    }
}

// fn main() {
//     use std::io::BufferedReader;
//     use std::io::File;
//     use std::str;

//     //let filetxt = BufferedReader::new(File::open(&Path::new("/usr/local/src/rust/src/libstd/prelude.rs"))).read_to_end().unwrap();
//     //let filetxt = BufferedReader::new(File::open(&Path::new("/usr/local/src/rust/src/libstd/prelude.rs"))).read_to_end().unwrap();
//     let filetxt = BufferedReader::new(File::open(&Path::new("/usr/local/src/rust/src/libcollections/str.rs"))).read_to_end().unwrap();
//     let src = str::from_utf8(filetxt.as_slice()).unwrap();

//     for (start,end) in code_chunks(src) {
//         println!("BLOB |{}|",src.slice(start,end));
//     }

// }
<commit_msg>codecleaner: fix to skip single quote chars<commit_after>//#[cfg(test)] use racer::testutils::{rejustify, slice};

pub fn rejustify(src: &str) -> String {
    let s = &src[1..]; // remove the newline
    let mut sb = String::new();
    for l in s.lines() {
        let tabless = &l[4..];
        sb.push_str(tabless);
        if tabless.len() != 0 {
            sb.push_str("\n");
        }
    }
    let newlen = sb.len()-1; // remove the trailing newline
    sb.truncate(newlen);
    sb
}

pub fn slice(src: &str, (begin, end): (usize, usize)) -> &str{
    &src[begin..end]
}

enum State {
    StateCode,
    StateComment,
    StateCommentBlock,
    StateString,
    StateChar,
    StateFinished
}

pub struct CodeIndicesIter<'a> {
    src: &'a str,
    pos: usize,
    state: State
}

impl<'a> Iterator for CodeIndicesIter<'a> {
    type Item = (usize, usize);

    #[inline]
    fn next(&mut self) -> Option<(usize, usize)> {
        let res = match self.state {
            State::StateCode => Some(code(self)),
            State::StateComment => Some(comment(self)),
            State::StateCommentBlock  => Some(comment_block(self)),
            State::StateString => Some(string(self)),
            State::StateChar => Some(char(self)),
            State::StateFinished => None
        };
        res
    }
}

fn code(self_: &mut CodeIndicesIter) -> (usize,usize) {

    let start = match self_.state {
        State::StateString | State::StateChar => { self_.pos-1 }, // include quote
        _ => { self_.pos }
    };
    let src_bytes = self_.src.as_bytes();
    for &b in src_bytes[self_.pos..].iter(){
        self_.pos += 1;
        match b {
            b'/' => match src_bytes[self_.pos] {
                b'/' => {
                    self_.state = State::StateComment;
                    self_.pos +=1;
                    return (start, self_.pos-2);
                },
                b'*' => {
                    self_.state = State::StateCommentBlock;
                    self_.pos +=1;
                    return (start, self_.pos-2);
                },
                _ => {}
            },
            b'"' => {    // "
                self_.state = State::StateString;
                return (start, self_.pos); // include dblquotes
            },
            b'\'' => {
                self_.state = State::StateChar;
                return (start, self_.pos); // include single quote
            },
            _ => {}
        }
    }

    self_.state = State::StateFinished;
    (start, self_.src.len())
}

fn comment(self_: &mut CodeIndicesIter) -> (usize,usize) {
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        if b == b'\n' { break; }
    }
    code(self_)
}

fn comment_block(self_: &mut CodeIndicesIter) -> (usize,usize) {

    let mut nesting_level = 0u16; // should be enough
    let mut prev = b' ';
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        match b {
            b'/' if prev == b'*' => {
                if nesting_level == 0 {
                    break;
                } else {
                    nesting_level -= 1;
                }
            },
            b'*' if prev == b'/' => {
                nesting_level += 1;
            },
            _ => { prev = b; }
        }
    }
    code(self_)
}

fn string(self_: &mut CodeIndicesIter) -> (usize,usize) {
    let mut is_not_escaped = true;
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        match b {
            b'"' if is_not_escaped  => { break; }, // "
            b'\\' => { is_not_escaped = !is_not_escaped; },
            _ => { is_not_escaped = true; }
        }
    }
    code(self_)
}

fn char(self_: &mut CodeIndicesIter) -> (usize,usize) {
    let mut is_not_escaped = true;
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        match b {
            b'\'' if is_not_escaped  => { break; },
            b'\\' => { is_not_escaped = !is_not_escaped; },
            _ => { is_not_escaped = true; }
        }
    }
    code(self_)
}

/// Returns indices of chunks of code (minus comments and string contents)
pub fn code_chunks<'a>(src: &'a str) -> CodeIndicesIter<'a> {
    CodeIndicesIter { src: src, state: State::StateCode, pos: 0 }
}

#[test]
fn removes_a_comment() {
    let src = &rejustify("
    this is some code // this is a comment
    some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_contents() {
    let src = &rejustify("
    this is some code \"this is a string\" more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_char_contents() {
    let src = &rejustify("
    this is some code \'\"\' more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \'", slice(src, it.next().unwrap()));
    assert_eq!("\' more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_contents_with_a_comment_in_it() {
    let src = &rejustify("
    this is some code \"string with a // fake comment \" more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_a_comment_with_a_dbl_quote_in_it() {
    let src = &rejustify("
    this is some code // comment with \" double quote
    some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_multiline_comment() {
    let src = &rejustify("
    this is some code /* this is a
    \"multiline\" comment */some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn handles_nesting_of_block_comments() {
    let src = &rejustify("
    this is some code /* nested /* block */ comment */ some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!(" some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_with_escaped_dblquote_in_it() {
    let src = &rejustify("
    this is some code \"string with a \\\" escaped dblquote fake comment \" more code
    ")[];

    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_with_escaped_slash_before_dblquote_in_it() {
    let src = &rejustify("
    this is some code \"string with an escaped slash, so dbl quote does end the string after all \\\\\" more code
    ")[];

    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn handles_tricky_bit_from_str_rs() {
    let src = &rejustify("
        before(\"\\\\\'\\\\\\\"\\\\\\\\\");
        more_code(\" skip me \")
    ")[];

    for (start,end) in code_chunks(src) {
        println!("BLOB |{}|",&src[start..end]);
        if (&src[start..end]).contains("skip me") {
            panic!("{}", &src[start..end]);
        }
    }
}

// fn main() {
//     use std::old_io::BufferedReader;
//     use std::old_io::File;
//     use std::str;

//     let filetxt = BufferedReader::new(File::open(&Path::new("/tmp/testcode.rs"))).read_to_end().unwrap();
//     let src = str::from_utf8(filetxt.as_slice()).unwrap();

//     for (start,end) in code_chunks(src) {
//         println!("BLOB |{}|",src.slice(start,end));
//     }

// }
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// 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.

#![crate_id="platformtree_macro"]
#![crate_type="dylib"]

#![feature(macro_registrar, quote, managed_boxes)]

extern crate syntax;

use syntax::ast::{Name, TokenTree};
use syntax::ast;
use syntax::codemap::{Span};
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt};
use syntax::ext::base::{MacResult, MacExpr};
use syntax::ext::base;
use syntax::parse::{token, ParseSess, lexer};
use syntax::print::pprust::expr_to_str;
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::{ToTokens, ExtParseUtils};

use std::collections::hashmap;

mod pt;

#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
  register(token::intern("platformtree_parse"), NormalTT(
    box BasicMacroExpander {
      expander: platformtree_parse,
      span: None,
    },
    None)
  );
}

/// Parse paltformtree to pt::Node
pub fn platformtree_parse(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
    -> Box<MacResult> {
  let mut parser = Parser::new(cx, tts);

  let node = parser.parse_node();

  println!("PT parsed: {}", node);

  base::MacExpr::new(quote_expr!(&*cx, $node))
}

impl pt::Node {
  pub fn to_source(&self) -> String {
    let mappath: Vec<String> = self.path.path.iter().map(|x| format!("\"{}\".to_string()", x)).collect();
    let node_struct = format!("pt::Node \\{ \
        name: {}, \
        path: pt::Path \\{ absolute: {}, path: vec!({}) \\}, \
        attributes: hashmap::HashMap::new(), \
        subnodes: Vec::new() \
      \\}",
      match self.name {
        Some(ref s) => format!("Some(\"{}\".to_string())", s),
        None => "None".to_string(),
      },
      self.path.absolute,
      mappath.connect(", "));

    let mut init_chunks = "".to_string();
    for (k, v) in self.attributes.iter() {
      let strinified_val = match v {
        &pt::UIntValue(ref u) => format!("pt::UIntValue({})", u),
        &pt::StrValue(ref s)  => format!("pt::StrValue(\"{}\".to_string())", s),
        &pt::RefValue(ref r)  => format!("pt::RefValue(\"{}\".to_string())", r),
      };

      init_chunks = init_chunks.append(format!("attrs.insert(\"{}\".to_string(), {});",
          k, strinified_val).as_slice());
    }

    for sn in self.subnodes.iter() {
      init_chunks = init_chunks.append(format!(
          "nodes.push(box {});", sn.to_source()).as_slice());
    }

    // TODO(farcaller): this triggers unused_mut for some reason.
    let init_struct = format!("
      \\{
        let mut node = {};
        let mut attrs = hashmap::HashMap::new();
        let mut nodes = Vec::new();
        {}
        node.attributes = attrs;
        node.subnodes = nodes;
        node
      \\}", node_struct, init_chunks);

    init_struct
  }
}

impl ToTokens for pt::Node {
  fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
    (cx as &ExtParseUtils).parse_tts(self.to_source())
  }
}

struct Parser<'a> {
  pub sess: &'a ParseSess,
  reader: Box<lexer::Reader:>,

  token: token::Token,
  span: Span,

  last_token: Option<Box<token::Token>>,
  last_span: Span,

  backlog: Vec<lexer::TokenAndSpan>,
}

impl<'a> Parser<'a> {
  pub fn new<'a>(cx: &'a ExtCtxt, tts: &[TokenTree]) -> Parser<'a> {
    let sess = cx.parse_sess();
    let ttsvec = tts.iter().map(|x| (*x).clone()).collect();
    let mut reader = box lexer::new_tt_reader(&sess.span_diagnostic, None, ttsvec)
        as Box<lexer::Reader>;

    let tok0 = reader.next_token();
    let token = tok0.tok;
    let span = tok0.sp;

    Parser {
      sess: sess,
      reader: reader,

      token: token,
      span: span,

      last_token: None,
      last_span: span,

      backlog: Vec::new(),
    }
  }

  fn fatal(&self, m: &str) -> ! {
    self.sess.span_diagnostic.span_fatal(self.span, m);
  }

  fn bump(&mut self) -> token::Token {
    let tok = self.token.clone();
    self.last_span = self.span;
    self.last_token = Some(box tok.clone());

    let next = match self.backlog.pop() {
      Some(ts) => ts,
      None => self.reader.next_token(),
    };

    self.span = next.sp;
    self.token = next.tok;

    tok
  }

  fn unbump(&mut self) {
    let span = self.last_span;
    let boxtok: &Box<token::Token> = match self.last_token {
      Some(ref t) => t,
      None => fail!(),
    };
    let tok = *boxtok.clone();

    self.backlog.push(lexer::TokenAndSpan {
      tok: self.token.clone(),
      sp: self.span,
    });

    self.token = tok;
    self.span = span;
  }

  fn expect(&mut self, t: &token::Token) {
    if self.token == *t {
      self.bump();
    } else {
      let token_str = token::to_str(t);
      let this_token_str = token::to_str(&self.token);
      self.fatal(format!("expected `{}` but found `{}`", token_str, this_token_str).as_slice())
    }
  }

  fn expect_ident(&mut self) -> token::Token {
    match self.token {
      token::IDENT(_, _) => {
        self.bump()
      },
      _ => {
        let this_token_str = token::to_str(&self.token);
        self.fatal(format!("expected identifier but found `{}`", this_token_str).as_slice())
      },
    }
  }

  pub fn parse_node(&mut self) -> pt::Node {
    let mut node = pt::Node::new();
    // NODE_ID @ NODE_PATH { CONTENTS }
    // or
    //         @ NODE_PATH { CONTENTS }

    node.name = match self.token {
      token::IDENT(_, _) => {
        let ret = Some(token::to_str(&self.token));
        self.bump();
        ret
      },
      token::AT => {
        None
      },
      _ => {
        let this_token_str = token::to_str(&self.token);
        self.fatal(format!("expected identifier or `@` but found `{}`", this_token_str).as_slice())
      },
    };

    self.expect(&token::AT);

    node.path = self.parse_path();

    self.expect(&token::LBRACE);
    self.parse_node_contents(&mut node);
    self.expect(&token::RBRACE);

    node
  }

  pub fn parse_node_contents(&mut self, node: &mut pt::Node) {
    let mut attrs = hashmap::HashMap::new();
    let mut nodes = Vec::new();

    loop {
      match self.token {
        token::RBRACE => break,
        token::IDENT(_, _) => {
          let name = token::to_str(&self.token);
          self.bump();

          match self.token {
            token::EQ => {
              self.bump();
              let val = self.parse_attribute_value();
              self.expect(&token::SEMI);

              attrs.insert(name, val);
            },
            token::AT => {
              self.unbump();
              let node = self.parse_node();
              nodes.push(box node);
            },
            _ => {
              let this_token_str = token::to_str(&self.token);
              self.fatal(format!("expected `@` or `=` but found `{}`", this_token_str).as_slice())
            }
          };
        }
        _ => {
          let this_token_str = token::to_str(&self.token);
          self.fatal(format!("expected identifier or `\\}` but found `{}`", this_token_str).as_slice())
        }
      }
    }

    node.attributes = attrs;
    node.subnodes = nodes;
  }

  pub fn parse_attribute_value(&mut self) -> pt::AttributeValue {
    let val = match self.token {
      token::LIT_STR(sv) => {
        let val = pt::StrValue(token::get_ident(sv).get().to_string());
        self.bump();
        val
      },
      token::LIT_INT_UNSUFFIXED(intval) => {
        let val = pt::UIntValue(intval as uint);
        self.bump();
        val
      },
      token::BINOP(token::AND) => {
        self.bump();
        pt::RefValue(token::to_str(&self.expect_ident()).to_string())
      },
      _ => {
        let this_token_str = token::to_str(&self.token);
        self.fatal(format!("expected integer or string but found {} `{}`", self.token, this_token_str).as_slice())
      }
    };

    val
  }

  pub fn parse_path(&mut self) -> pt::Path {
    let mut v = Vec::new();
    let mut expect_more = false;
    let mut absolute = false;

    if self.token == token::MOD_SEP {
      self.bump();
      expect_more = true;
      absolute = true;
    }

    loop {
      match self.token {
        token::MOD_SEP => {
          if expect_more {
            let this_token_str = token::to_str(&self.token);
            self.fatal(format!("expected identifier but found `{}`", this_token_str).as_slice())
          }
          self.bump();
          expect_more = true;
        },
        token::IDENT(_, _) => {
          v.push(token::to_str(&self.token));
          self.bump();
          expect_more = false;
        },
        token::LIT_INT_UNSUFFIXED(u) => {
          v.push(u.to_str());
          self.bump();
          expect_more = false;
        }
        _ => {
          if !expect_more {
            if v.len() == 0 {
              self.fatal(format!("unfinished path, found {} `{}`", self.token,
                  token::to_str(&self.token)).as_slice());
            }
            break
          } else {
            self.fatal(format!("unfinished path, found {} `{}`", self.token,
                token::to_str(&self.token)).as_slice());
          }
        }
      }
    }
    pt::Path {
      absolute: absolute,
      path: v,
    }
  }
}
<commit_msg>Fail if there are trailing tokens after parsing root PT node.<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// 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.

#![crate_id="platformtree_macro"]
#![crate_type="dylib"]

#![feature(macro_registrar, quote, managed_boxes)]

extern crate syntax;

use syntax::ast::{Name, TokenTree};
use syntax::ast;
use syntax::codemap::{Span};
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt};
use syntax::ext::base::{MacResult, MacExpr};
use syntax::ext::base;
use syntax::parse::{token, ParseSess, lexer};
use syntax::print::pprust::expr_to_str;
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::{ToTokens, ExtParseUtils};

use std::collections::hashmap;

mod pt;

#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
  register(token::intern("platformtree_parse"), NormalTT(
    box BasicMacroExpander {
      expander: platformtree_parse,
      span: None,
    },
    None)
  );
}

/// Parse paltformtree to pt::Node
pub fn platformtree_parse(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
    -> Box<MacResult> {
  let mut parser = Parser::new(cx, tts);

  let node = parser.parse_node();
  parser.should_finish();

  println!("PT parsed: {}", node);

  base::MacExpr::new(quote_expr!(&*cx, $node))
}

impl pt::Node {
  pub fn to_source(&self) -> String {
    let mappath: Vec<String> = self.path.path.iter().map(|x| format!("\"{}\".to_string()", x)).collect();
    let node_struct = format!("pt::Node \\{ \
        name: {}, \
        path: pt::Path \\{ absolute: {}, path: vec!({}) \\}, \
        attributes: hashmap::HashMap::new(), \
        subnodes: Vec::new() \
      \\}",
      match self.name {
        Some(ref s) => format!("Some(\"{}\".to_string())", s),
        None => "None".to_string(),
      },
      self.path.absolute,
      mappath.connect(", "));

    let mut init_chunks = "".to_string();
    for (k, v) in self.attributes.iter() {
      let strinified_val = match v {
        &pt::UIntValue(ref u) => format!("pt::UIntValue({})", u),
        &pt::StrValue(ref s)  => format!("pt::StrValue(\"{}\".to_string())", s),
        &pt::RefValue(ref r)  => format!("pt::RefValue(\"{}\".to_string())", r),
      };

      init_chunks = init_chunks.append(format!("attrs.insert(\"{}\".to_string(), {});",
          k, strinified_val).as_slice());
    }

    for sn in self.subnodes.iter() {
      init_chunks = init_chunks.append(format!(
          "nodes.push(box {});", sn.to_source()).as_slice());
    }

    // TODO(farcaller): this triggers unused_mut for some reason.
    let init_struct = format!("
      \\{
        let mut node = {};
        let mut attrs = hashmap::HashMap::new();
        let mut nodes = Vec::new();
        {}
        node.attributes = attrs;
        node.subnodes = nodes;
        node
      \\}", node_struct, init_chunks);

    init_struct
  }
}

impl ToTokens for pt::Node {
  fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
    (cx as &ExtParseUtils).parse_tts(self.to_source())
  }
}

struct Parser<'a> {
  pub sess: &'a ParseSess,
  reader: Box<lexer::Reader:>,

  token: token::Token,
  span: Span,

  last_token: Option<Box<token::Token>>,
  last_span: Span,

  backlog: Vec<lexer::TokenAndSpan>,
}

impl<'a> Parser<'a> {
  pub fn new<'a>(cx: &'a ExtCtxt, tts: &[TokenTree]) -> Parser<'a> {
    let sess = cx.parse_sess();
    let ttsvec = tts.iter().map(|x| (*x).clone()).collect();
    let mut reader = box lexer::new_tt_reader(&sess.span_diagnostic, None, ttsvec)
        as Box<lexer::Reader>;

    let tok0 = reader.next_token();
    let token = tok0.tok;
    let span = tok0.sp;

    Parser {
      sess: sess,
      reader: reader,

      token: token,
      span: span,

      last_token: None,
      last_span: span,

      backlog: Vec::new(),
    }
  }

  fn fatal(&self, m: &str) -> ! {
    self.sess.span_diagnostic.span_fatal(self.span, m);
  }

  fn bump(&mut self) -> token::Token {
    let tok = self.token.clone();
    self.last_span = self.span;
    self.last_token = Some(box tok.clone());

    let next = match self.backlog.pop() {
      Some(ts) => ts,
      None => self.reader.next_token(),
    };

    self.span = next.sp;
    self.token = next.tok;

    tok
  }

  fn unbump(&mut self) {
    let span = self.last_span;
    let boxtok: &Box<token::Token> = match self.last_token {
      Some(ref t) => t,
      None => fail!(),
    };
    let tok = *boxtok.clone();

    self.backlog.push(lexer::TokenAndSpan {
      tok: self.token.clone(),
      sp: self.span,
    });

    self.token = tok;
    self.span = span;
  }

  fn expect(&mut self, t: &token::Token) {
    if self.token == *t {
      self.bump();
    } else {
      let token_str = token::to_str(t);
      let this_token_str = token::to_str(&self.token);
      self.fatal(format!("expected `{}` but found `{}`", token_str, this_token_str).as_slice());
    }
  }

  fn expect_ident(&mut self) -> token::Token {
    match self.token {
      token::IDENT(_, _) => {
        self.bump()
      },
      _ => {
        let this_token_str = token::to_str(&self.token);
        self.fatal(format!("expected identifier but found `{}`", this_token_str).as_slice());
      },
    }
  }

  pub fn should_finish(&mut self) {
    if self.bump() != token::EOF {
      let this_token_str = token::to_str(&self.token);
      self.fatal(format!("trailing garbage: `{}`", this_token_str).as_slice());
    }
  }

  pub fn parse_node(&mut self) -> pt::Node {
    let mut node = pt::Node::new();
    // NODE_ID @ NODE_PATH { CONTENTS }
    // or
    //         @ NODE_PATH { CONTENTS }

    node.name = match self.token {
      token::IDENT(_, _) => {
        let ret = Some(token::to_str(&self.token));
        self.bump();
        ret
      },
      token::AT => {
        None
      },
      _ => {
        let this_token_str = token::to_str(&self.token);
        self.fatal(format!("expected identifier or `@` but found `{}`", this_token_str).as_slice())
      },
    };

    self.expect(&token::AT);

    node.path = self.parse_path();

    self.expect(&token::LBRACE);
    self.parse_node_contents(&mut node);
    self.expect(&token::RBRACE);

    node
  }

  pub fn parse_node_contents(&mut self, node: &mut pt::Node) {
    let mut attrs = hashmap::HashMap::new();
    let mut nodes = Vec::new();

    loop {
      match self.token {
        token::RBRACE => break,
        token::IDENT(_, _) => {
          let name = token::to_str(&self.token);
          self.bump();

          match self.token {
            token::EQ => {
              self.bump();
              let val = self.parse_attribute_value();
              self.expect(&token::SEMI);

              attrs.insert(name, val);
            },
            token::AT => {
              self.unbump();
              let node = self.parse_node();
              nodes.push(box node);
            },
            _ => {
              let this_token_str = token::to_str(&self.token);
              self.fatal(format!("expected `@` or `=` but found `{}`", this_token_str).as_slice())
            }
          };
        }
        _ => {
          let this_token_str = token::to_str(&self.token);
          self.fatal(format!("expected identifier or `\\}` but found `{}`", this_token_str).as_slice())
        }
      }
    }

    node.attributes = attrs;
    node.subnodes = nodes;
  }

  pub fn parse_attribute_value(&mut self) -> pt::AttributeValue {
    let val = match self.token {
      token::LIT_STR(sv) => {
        let val = pt::StrValue(token::get_ident(sv).get().to_string());
        self.bump();
        val
      },
      token::LIT_INT_UNSUFFIXED(intval) => {
        let val = pt::UIntValue(intval as uint);
        self.bump();
        val
      },
      token::BINOP(token::AND) => {
        self.bump();
        pt::RefValue(token::to_str(&self.expect_ident()).to_string())
      },
      _ => {
        let this_token_str = token::to_str(&self.token);
        self.fatal(format!("expected integer or string but found {} `{}`", self.token, this_token_str).as_slice())
      }
    };

    val
  }

  pub fn parse_path(&mut self) -> pt::Path {
    let mut v = Vec::new();
    let mut expect_more = false;
    let mut absolute = false;

    if self.token == token::MOD_SEP {
      self.bump();
      expect_more = true;
      absolute = true;
    }

    loop {
      match self.token {
        token::MOD_SEP => {
          if expect_more {
            let this_token_str = token::to_str(&self.token);
            self.fatal(format!("expected identifier but found `{}`", this_token_str).as_slice())
          }
          self.bump();
          expect_more = true;
        },
        token::IDENT(_, _) => {
          v.push(token::to_str(&self.token));
          self.bump();
          expect_more = false;
        },
        token::LIT_INT_UNSUFFIXED(u) => {
          v.push(u.to_str());
          self.bump();
          expect_more = false;
        }
        _ => {
          if !expect_more {
            if v.len() == 0 {
              self.fatal(format!("unfinished path, found {} `{}`", self.token,
                  token::to_str(&self.token)).as_slice());
            }
            break
          } else {
            self.fatal(format!("unfinished path, found {} `{}`", self.token,
                token::to_str(&self.token)).as_slice());
          }
        }
      }
    }
    pt::Path {
      absolute: absolute,
      path: v,
    }
  }
}
<|endoftext|>


<commit_before>#![crate_name = "platform"]
#![crate_type = "rlib"]
#![no_std]
#![feature(const_fn,lang_items)]

extern crate common;
extern crate drivers;
extern crate hil;
extern crate sam4l;
extern crate support;

use hil::Controller;
use hil::spi_master::SpiMaster;
use drivers::timer::AlarmToTimer;
use drivers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};

#[macro_use]
pub mod io;

// HAL unit tests. To enable a particular unit test, uncomment
// the module here and uncomment the call to start the test in
// the init function below.
//mod gpio_dummy;
//mod spi_dummy;
mod i2c_dummy;

static mut spi_read_buf:  [u8; 64] = [0; 64];
static mut spi_write_buf: [u8; 64] = [0; 64];

pub struct Firestorm {
    chip: sam4l::chip::Sam4l,
    console: &'static drivers::console::Console<'static, sam4l::usart::USART>,
    gpio: drivers::gpio::GPIO<[&'static hil::gpio::GPIOPin; 13]>,
    timer: &'static drivers::timer::TimerDriver<'static, AlarmToTimer<'static,
                                VirtualMuxAlarm<'static, sam4l::ast::Ast>>>,
    tmp006: &'static drivers::tmp006::TMP006<'static, sam4l::i2c::I2CDevice, sam4l::gpio::GPIOPin>,
    spi: &'static drivers::spi::Spi<'static, sam4l::spi::Spi>,
}

impl Firestorm {
    pub unsafe fn service_pending_interrupts(&mut self) {
        self.chip.service_pending_interrupts()
    }

    pub unsafe fn has_pending_interrupts(&mut self) -> bool {
        self.chip.has_pending_interrupts()
    }

    pub fn with_driver<F, R>(&mut self, driver_num: usize, f: F) -> R where
            F: FnOnce(Option<&hil::Driver>) -> R {

        match driver_num {
            0 => f(Some(self.console)),
            1 => f(Some(&self.gpio)),
            2 => f(Some(self.tmp006)),
            3 => f(Some(self.timer)),
            4 => f(Some(self.spi)),
            _ => f(None)
        }
    }
}

macro_rules! static_init {
   ($V:ident : $T:ty = $e:expr) => {
        let $V : &mut $T = {
            // Waiting out for size_of to be available at compile-time to avoid
            // hardcoding an abitrary large size...
            static mut BUF : [u8; 1024] = [0; 1024];
            let mut tmp : &mut $T = mem::transmute(&mut BUF);
            *tmp = $e;
            tmp
        };
   }
}

pub unsafe fn init<'a>() -> &'a mut Firestorm {
    use core::mem;

    // Workaround for SB.02 hardware bug
    // TODO(alevy): Get rid of this when we think SB.02 are out of circulation
    sam4l::gpio::PA[14].enable();
    sam4l::gpio::PA[14].set();
    sam4l::gpio::PA[14].enable_output();

    static_init!(console : drivers::console::Console<sam4l::usart::USART> =
                    drivers::console::Console::new(&sam4l::usart::USART3,
                                       &mut drivers::console::WRITE_BUF));
    sam4l::usart::USART3.set_client(console);

    let ast = &sam4l::ast::AST;

    static_init!(mux_alarm : MuxAlarm<'static, sam4l::ast::Ast> =
                    MuxAlarm::new(&sam4l::ast::AST));
    ast.configure(mux_alarm);

    // the i2c address of the device is 0x40
    static_init!(tmp006 : drivers::tmp006::TMP006<'static, sam4l::i2c::I2CDevice, sam4l::gpio::GPIOPin> =
                    drivers::tmp006::TMP006::new(&sam4l::i2c::I2C2, 0x40, &sam4l::gpio::PA[9]));
    sam4l::gpio::PA[9].set_client(tmp006);

    static_init!(virtual_alarm1 : VirtualMuxAlarm<'static, sam4l::ast::Ast> =
                    VirtualMuxAlarm::new(mux_alarm));
    static_init!(vtimer1 : AlarmToTimer<'static,
                                VirtualMuxAlarm<'static, sam4l::ast::Ast>> =
                            AlarmToTimer::new(virtual_alarm1));
    virtual_alarm1.set_client(vtimer1);
    static_init!(timer : drivers::timer::TimerDriver<AlarmToTimer<'static,
                                VirtualMuxAlarm<'static, sam4l::ast::Ast>>> =
                            drivers::timer::TimerDriver::new(vtimer1));
    vtimer1.set_client(timer);

    // Configure SPI pins: CLK, MISO, MOSI, CS3
    sam4l::gpio::PC[ 6].configure(Some(sam4l::gpio::PeripheralFunction::A));
    sam4l::gpio::PC[ 4].configure(Some(sam4l::gpio::PeripheralFunction::A));
    sam4l::gpio::PC[ 5].configure(Some(sam4l::gpio::PeripheralFunction::A));
    sam4l::gpio::PC[ 1].configure(Some(sam4l::gpio::PeripheralFunction::A));
    // Initialize and enable SPI HAL
    static_init!(spi: drivers::spi::Spi<'static, sam4l::spi::Spi> =
                      drivers::spi::Spi::new(&mut sam4l::spi::SPI));
    spi.config_buffers(&mut spi_read_buf, &mut spi_write_buf);
    sam4l::spi::SPI.set_active_peripheral(sam4l::spi::Peripheral::Peripheral1);
    sam4l::spi::SPI.init(spi as &hil::spi_master::SpiCallback);
    sam4l::spi::SPI.enable();

    static_init!(firestorm : Firestorm = Firestorm {
        chip: sam4l::chip::Sam4l::new(),
        console: &*console,
        gpio: drivers::gpio::GPIO::new(
            [ &sam4l::gpio::PC[10], &sam4l::gpio::PC[19]
            , &sam4l::gpio::PC[13], &sam4l::gpio::PA[17]
            , &sam4l::gpio::PC[20], &sam4l::gpio::PA[19]
            , &sam4l::gpio::PA[14], &sam4l::gpio::PA[16]
            , &sam4l::gpio::PA[13], &sam4l::gpio::PA[11]
            , &sam4l::gpio::PA[10], &sam4l::gpio::PA[12]
            , &sam4l::gpio::PC[09]]),
        timer: timer,
        tmp006: &*tmp006,
        spi: &*spi,
    });

    sam4l::usart::USART3.configure(sam4l::usart::USARTParams {
        //client: &console,
        baud_rate: 115200,
        data_bits: 8,
        parity: hil::uart::Parity::None
    });

    sam4l::gpio::PB[09].configure(Some(sam4l::gpio::PeripheralFunction::A));
    sam4l::gpio::PB[10].configure(Some(sam4l::gpio::PeripheralFunction::A));

    // Configure I2C SDA and SCL pins
    sam4l::gpio::PA[21].configure(Some(sam4l::gpio::PeripheralFunction::E));
    sam4l::gpio::PA[22].configure(Some(sam4l::gpio::PeripheralFunction::E));

    // Uncommenting the following line will cause the device to use the
    // SPI HAL to write [8, 7, 6, 5, 4, 3, 2, 1] once over the SPI then
    // echo the 8 bytes read from the slave continuously.
    //spi_dummy::spi_dummy_test();

    // Uncommenting the following line will toggle the LED whenever the value of
    // Firestorm's pin 8 changes value (e.g., connect a push button to pin 8 and
    // press toggle it).
    //gpio_dummy::gpio_dummy_test();

    // Uncommenting the following line will test the I2C
    //i2c_dummy::i2c_scan_slaves();
    i2c_dummy::i2c_tmp006_test();
    //i2c_dummy::i2c_accel_test();
    //i2c_dummy::i2c_li_test();

    firestorm.console.initialize();

    firestorm
}

<commit_msg>Firestorm: comment out i2c test code<commit_after>#![crate_name = "platform"]
#![crate_type = "rlib"]
#![no_std]
#![feature(const_fn,lang_items)]

extern crate common;
extern crate drivers;
extern crate hil;
extern crate sam4l;
extern crate support;

use hil::Controller;
use hil::spi_master::SpiMaster;
use drivers::timer::AlarmToTimer;
use drivers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};

#[macro_use]
pub mod io;

// HAL unit tests. To enable a particular unit test, uncomment
// the module here and uncomment the call to start the test in
// the init function below.
//mod gpio_dummy;
//mod spi_dummy;
//mod i2c_dummy;

static mut spi_read_buf:  [u8; 64] = [0; 64];
static mut spi_write_buf: [u8; 64] = [0; 64];

pub struct Firestorm {
    chip: sam4l::chip::Sam4l,
    console: &'static drivers::console::Console<'static, sam4l::usart::USART>,
    gpio: drivers::gpio::GPIO<[&'static hil::gpio::GPIOPin; 13]>,
    timer: &'static drivers::timer::TimerDriver<'static, AlarmToTimer<'static,
                                VirtualMuxAlarm<'static, sam4l::ast::Ast>>>,
    tmp006: &'static drivers::tmp006::TMP006<'static, sam4l::i2c::I2CDevice, sam4l::gpio::GPIOPin>,
    spi: &'static drivers::spi::Spi<'static, sam4l::spi::Spi>,
}

impl Firestorm {
    pub unsafe fn service_pending_interrupts(&mut self) {
        self.chip.service_pending_interrupts()
    }

    pub unsafe fn has_pending_interrupts(&mut self) -> bool {
        self.chip.has_pending_interrupts()
    }

    pub fn with_driver<F, R>(&mut self, driver_num: usize, f: F) -> R where
            F: FnOnce(Option<&hil::Driver>) -> R {

        match driver_num {
            0 => f(Some(self.console)),
            1 => f(Some(&self.gpio)),
            2 => f(Some(self.tmp006)),
            3 => f(Some(self.timer)),
            4 => f(Some(self.spi)),
            _ => f(None)
        }
    }
}

macro_rules! static_init {
   ($V:ident : $T:ty = $e:expr) => {
        let $V : &mut $T = {
            // Waiting out for size_of to be available at compile-time to avoid
            // hardcoding an abitrary large size...
            static mut BUF : [u8; 1024] = [0; 1024];
            let mut tmp : &mut $T = mem::transmute(&mut BUF);
            *tmp = $e;
            tmp
        };
   }
}

pub unsafe fn init<'a>() -> &'a mut Firestorm {
    use core::mem;

    // Workaround for SB.02 hardware bug
    // TODO(alevy): Get rid of this when we think SB.02 are out of circulation
    sam4l::gpio::PA[14].enable();
    sam4l::gpio::PA[14].set();
    sam4l::gpio::PA[14].enable_output();

    static_init!(console : drivers::console::Console<sam4l::usart::USART> =
                    drivers::console::Console::new(&sam4l::usart::USART3,
                                       &mut drivers::console::WRITE_BUF));
    sam4l::usart::USART3.set_client(console);

    let ast = &sam4l::ast::AST;

    static_init!(mux_alarm : MuxAlarm<'static, sam4l::ast::Ast> =
                    MuxAlarm::new(&sam4l::ast::AST));
    ast.configure(mux_alarm);

    // the i2c address of the device is 0x40
    static_init!(tmp006 : drivers::tmp006::TMP006<'static, sam4l::i2c::I2CDevice, sam4l::gpio::GPIOPin> =
                    drivers::tmp006::TMP006::new(&sam4l::i2c::I2C2, 0x40, &sam4l::gpio::PA[9]));
    sam4l::gpio::PA[9].set_client(tmp006);

    static_init!(virtual_alarm1 : VirtualMuxAlarm<'static, sam4l::ast::Ast> =
                    VirtualMuxAlarm::new(mux_alarm));
    static_init!(vtimer1 : AlarmToTimer<'static,
                                VirtualMuxAlarm<'static, sam4l::ast::Ast>> =
                            AlarmToTimer::new(virtual_alarm1));
    virtual_alarm1.set_client(vtimer1);
    static_init!(timer : drivers::timer::TimerDriver<AlarmToTimer<'static,
                                VirtualMuxAlarm<'static, sam4l::ast::Ast>>> =
                            drivers::timer::TimerDriver::new(vtimer1));
    vtimer1.set_client(timer);

    // Configure SPI pins: CLK, MISO, MOSI, CS3
    sam4l::gpio::PC[ 6].configure(Some(sam4l::gpio::PeripheralFunction::A));
    sam4l::gpio::PC[ 4].configure(Some(sam4l::gpio::PeripheralFunction::A));
    sam4l::gpio::PC[ 5].configure(Some(sam4l::gpio::PeripheralFunction::A));
    sam4l::gpio::PC[ 1].configure(Some(sam4l::gpio::PeripheralFunction::A));
    // Initialize and enable SPI HAL
    static_init!(spi: drivers::spi::Spi<'static, sam4l::spi::Spi> =
                      drivers::spi::Spi::new(&mut sam4l::spi::SPI));
    spi.config_buffers(&mut spi_read_buf, &mut spi_write_buf);
    sam4l::spi::SPI.set_active_peripheral(sam4l::spi::Peripheral::Peripheral1);
    sam4l::spi::SPI.init(spi as &hil::spi_master::SpiCallback);
    sam4l::spi::SPI.enable();

    static_init!(firestorm : Firestorm = Firestorm {
        chip: sam4l::chip::Sam4l::new(),
        console: &*console,
        gpio: drivers::gpio::GPIO::new(
            [ &sam4l::gpio::PC[10], &sam4l::gpio::PC[19]
            , &sam4l::gpio::PC[13], &sam4l::gpio::PA[17]
            , &sam4l::gpio::PC[20], &sam4l::gpio::PA[19]
            , &sam4l::gpio::PA[14], &sam4l::gpio::PA[16]
            , &sam4l::gpio::PA[13], &sam4l::gpio::PA[11]
            , &sam4l::gpio::PA[10], &sam4l::gpio::PA[12]
            , &sam4l::gpio::PC[09]]),
        timer: timer,
        tmp006: &*tmp006,
        spi: &*spi,
    });

    sam4l::usart::USART3.configure(sam4l::usart::USARTParams {
        //client: &console,
        baud_rate: 115200,
        data_bits: 8,
        parity: hil::uart::Parity::None
    });

    sam4l::gpio::PB[09].configure(Some(sam4l::gpio::PeripheralFunction::A));
    sam4l::gpio::PB[10].configure(Some(sam4l::gpio::PeripheralFunction::A));

    // Configure I2C SDA and SCL pins
    sam4l::gpio::PA[21].configure(Some(sam4l::gpio::PeripheralFunction::E));
    sam4l::gpio::PA[22].configure(Some(sam4l::gpio::PeripheralFunction::E));

    // Uncommenting the following line will cause the device to use the
    // SPI HAL to write [8, 7, 6, 5, 4, 3, 2, 1] once over the SPI then
    // echo the 8 bytes read from the slave continuously.
    //spi_dummy::spi_dummy_test();

    // Uncommenting the following line will toggle the LED whenever the value of
    // Firestorm's pin 8 changes value (e.g., connect a push button to pin 8 and
    // press toggle it).
    //gpio_dummy::gpio_dummy_test();

    // Uncommenting the following line will test the I2C
    //i2c_dummy::i2c_scan_slaves();
    //i2c_dummy::i2c_tmp006_test();
    //i2c_dummy::i2c_accel_test();
    //i2c_dummy::i2c_li_test();

    firestorm.console.initialize();

    firestorm
}

<|endoftext|>


<commit_before>/* This file is part of Grust, GObject introspection bindings for Rust
 *
 * Copyright (C) 2013  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

pub type gboolean       = libc::c_int;
pub type gchar          = libc::c_char;
pub type gint           = libc::c_int;
pub type guint          = libc::c_uint;
pub type gsize          = libc::size_t;

pub static FALSE: gboolean = 0;
pub static TRUE:  gboolean = !FALSE;
<commit_msg>grust/types.rs: Documented the purpose of the module<commit_after>/* This file is part of Grust, GObject introspection bindings for Rust
 *
 * Copyright (C) 2013  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

// This module provides types that are intrinsic in GIR, so they do not
// get defined through other types. It should ultimately have a name defined
// for every basic type listed in the documentation:
// https://live.gnome.org/GObjectIntrospection/Annotations#Default_Basic_Types
//
// Exceptions are:
// 1. Fixed-size integer types. These have straightforward machine-independent
//    counterparts in Rust.
// 2. Strings annotated as "utf8" or "filename". These types are not named
//    as such in the C API. There is no limitation for an introspected API
//    against providing its own "utf8" or "filename", so these types are
//    disambiguated in the generated code by qualifying their names with
//    a separate module, gstr.
//
// Rust aliases are needed for machine-dependent basic types used in GIR,
// since the GLib types are not necessarily identical to their Rust namesakes
// (the issue similarly addressed by std::libc::c_int and the like).
// Usage of the GLib typedef names prevents potential name conflicts,
// because the introspected C API is likely to compile with the GLib type
// definitions, and it's highly unlikely for these names to be given to
// something else via GI annotations.
//
// Any other GLib-derived types used by the bindings require some name
// disambiguation with definitions for the same C types that are emitted
// in "raw" namespaces of the generated GLib API crates (which are dependent,
// as any others, on the grust crate, so we cannot refer to their types here
// without creating a circular build dependency). Those type names should
// not be defined so as to be pulled in by 'use grust::types::*'.

pub type gboolean       = libc::c_int;
pub type gchar          = libc::c_char;
pub type gint           = libc::c_int;
pub type guint          = libc::c_uint;
pub type gsize          = libc::size_t;

pub static FALSE: gboolean = 0;
pub static TRUE:  gboolean = !FALSE;
<|endoftext|>