<commit_before>use url::Url;

// An incomplete container for all the kinds of events that we care about.
#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct HookBody {
    pub repository: Repo,
    pub sender: User,

    pub action: Option<String>,
    pub issue: Option<Issue>,
    pub comment: Option<Comment>,
    pub pull_request: Option<PullRequest>,
    pub review: Option<Review>,
    pub label: Option<Label>,

    // push event related stuff
    #[serde(rename = "ref")]
    pub ref_name: Option<String>,
    pub after: Option<String>,
    pub before: Option<String>,
    pub compare: Option<String>,
    pub forced: Option<bool>,
    pub deleted: Option<bool>,
    pub created: Option<bool>,
    pub commits: Option<Vec<Commit>>,
}

impl HookBody {
    pub fn ref_name(&self) -> &str {
        match self.ref_name {
            Some(ref v) => v,
            None => "",
        }
    }

    pub fn after(&self) -> &str {
        match self.after {
            Some(ref v) => v,
            None => "",
        }
    }

    pub fn before(&self) -> &str {
        match self.before {
            Some(ref v) => v,
            None => "",
        }
    }

    pub fn forced(&self) -> bool {
        self.forced.unwrap_or(false)
    }

    pub fn created(&self) -> bool {
        self.deleted.unwrap_or(false)
    }

    pub fn deleted(&self) -> bool {
        self.deleted.unwrap_or(false)
    }
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct User {
    pub login: Option<String>,
    pub name: Option<String>,
}

impl User {
    pub fn new(login: &str) -> User {
        User {
            login: Some(login.to_string()),
            name: Some(login.to_string()),
        }
    }

    pub fn login(&self) -> &str {
        if let Some(ref login) = self.login {
            login
        } else {
            ""
        }
    }

    pub fn name(&self) -> &str {
        if let Some(ref name) = self.name {
            name
        } else {
            ""
        }
    }
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct Repo {
    pub html_url: String,
    pub full_name: String,
    pub name: String,
    pub owner: User,
}

impl Repo {
    pub fn new() -> Repo {
        Repo {
            html_url: String::new(),
            full_name: String::new(),
            name: String::new(),
            owner: User::new(""),
        }
    }

    pub fn parse(html_url: &str) -> Result<Repo, String> {
        match Url::parse(html_url) {
            Ok(url) => {
                let segments: Vec<&str> = match url.path_segments() {
                    Some(s) => s.filter(|p| p.len() > 0).collect(),
                    None => return Err(format!("No path segments in URL")),
                };
                if segments.len() != 2 {
                    return Err(format!("Expectd only two path segments!"));
                }

                let user = segments[0];
                let repo = segments[1];

                Ok(Repo {
                    html_url: html_url.to_string(),
                    full_name: format!("{}/{}", user, repo),
                    name: repo.to_string(),
                    owner: User::new(user),
                })
            }
            Err(e) => return Err(format!("Error parsing url: {}", e)),
        }

    }
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct BranchRef {
    #[serde(rename = "ref")]
    pub ref_name: String,
    pub sha: String,
    pub user: User,
    pub repo: Repo,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct PullRequest {
    pub title: String,
    pub number: u32,
    pub html_url: String,
    pub state: String,
    pub user: User,
    pub merged: Option<bool>,
    pub merge_commit_sha: Option<String>,
    pub assignees: Vec<User>,
    pub head: BranchRef,
    pub base: BranchRef,
}

impl PullRequest {
    pub fn is_merged(&self) -> bool {
        self.merged.unwrap_or(false)
    }
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct Issue {
    pub html_url: String,
    pub title: String,
    pub user: User,
    pub assignees: Vec<User>,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct Label {
    pub name: String,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct Review {
    pub state: String,
    pub body: Option<String>,
    pub html_url: String,
    pub user: User,
}

impl Review {
    pub fn body(&self) -> &str {
        match self.body {
            Some(ref body) => body,
            None => "",
        }
    }
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct Comment {
    pub commit_id: Option<String>,
    pub path: Option<String>,
    pub body: Option<String>,
    pub html_url: String,
    pub user: User,
}

impl Comment {
    pub fn body(&self) -> &str {
        match self.body {
            Some(ref body) => body,
            None => "",
        }
    }
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct Commit {
    pub id: String,
    pub tree_id: String,
    pub message: String,
    pub url: String,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct AssignResponse {
    pub assignees: Vec<User>,
}

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

    #[test]
    fn test_repo_parse() {
        // note: trailing slash should'nt bother it
        let repo = Repo::parse("http://git.company.com/users/repo/").unwrap();

        assert_eq!("http://git.company.com/users/repo/", repo.html_url);
        assert_eq!("users/repo", repo.full_name);
        assert_eq!("users", repo.owner.login());
    }

    #[test]
    #[should_panic]
    fn test_repo_parse_no_repo() {
        Repo::parse("http://git.company.com/users/").unwrap();
    }

    #[test]
    #[should_panic]
    fn test_repo_parse_no_user() {
        Repo::parse("http://git.company.com/").unwrap();
    }

    #[test]
    #[should_panic]
    fn test_repo_parse_too_many_parts() {
        Repo::parse("http://git.company.com/users/repo/huh").unwrap();
    }
}
<commit_msg>Fix push event created flag (#24)<commit_after>use url::Url;

// An incomplete container for all the kinds of events that we care about.
#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct HookBody {
    pub repository: Repo,
    pub sender: User,

    pub action: Option<String>,
    pub issue: Option<Issue>,
    pub comment: Option<Comment>,
    pub pull_request: Option<PullRequest>,
    pub review: Option<Review>,
    pub label: Option<Label>,

    // push event related stuff
    #[serde(rename = "ref")]
    pub ref_name: Option<String>,
    pub after: Option<String>,
    pub before: Option<String>,
    pub compare: Option<String>,
    pub forced: Option<bool>,
    pub deleted: Option<bool>,
    pub created: Option<bool>,
    pub commits: Option<Vec<Commit>>,
}

impl HookBody {
    pub fn new() -> HookBody {
        HookBody {
            repository: Repo::new(),
            sender: User::new(""),
            action: None,
            issue: None,
            comment: None,
            pull_request: None,
            review: None,
            label: None,
            ref_name: None,
            after: None,
            before: None,
            compare: None,
            forced: None,
            deleted: None,
            created: None,
            commits: None,
        }
    }

    pub fn ref_name(&self) -> &str {
        match self.ref_name {
            Some(ref v) => v,
            None => "",
        }
    }

    pub fn after(&self) -> &str {
        match self.after {
            Some(ref v) => v,
            None => "",
        }
    }

    pub fn before(&self) -> &str {
        match self.before {
            Some(ref v) => v,
            None => "",
        }
    }

    pub fn forced(&self) -> bool {
        self.forced.unwrap_or(false)
    }

    pub fn created(&self) -> bool {
        self.created.unwrap_or(false)
    }

    pub fn deleted(&self) -> bool {
        self.deleted.unwrap_or(false)
    }
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct User {
    pub login: Option<String>,
    pub name: Option<String>,
}

impl User {
    pub fn new(login: &str) -> User {
        User {
            login: Some(login.to_string()),
            name: Some(login.to_string()),
        }
    }

    pub fn login(&self) -> &str {
        if let Some(ref login) = self.login {
            login
        } else {
            ""
        }
    }

    pub fn name(&self) -> &str {
        if let Some(ref name) = self.name {
            name
        } else {
            ""
        }
    }
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct Repo {
    pub html_url: String,
    pub full_name: String,
    pub name: String,
    pub owner: User,
}

impl Repo {
    pub fn new() -> Repo {
        Repo {
            html_url: String::new(),
            full_name: String::new(),
            name: String::new(),
            owner: User::new(""),
        }
    }

    pub fn parse(html_url: &str) -> Result<Repo, String> {
        match Url::parse(html_url) {
            Ok(url) => {
                let segments: Vec<&str> = match url.path_segments() {
                    Some(s) => s.filter(|p| p.len() > 0).collect(),
                    None => return Err(format!("No path segments in URL")),
                };
                if segments.len() != 2 {
                    return Err(format!("Expectd only two path segments!"));
                }

                let user = segments[0];
                let repo = segments[1];

                Ok(Repo {
                    html_url: html_url.to_string(),
                    full_name: format!("{}/{}", user, repo),
                    name: repo.to_string(),
                    owner: User::new(user),
                })
            }
            Err(e) => return Err(format!("Error parsing url: {}", e)),
        }

    }
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct BranchRef {
    #[serde(rename = "ref")]
    pub ref_name: String,
    pub sha: String,
    pub user: User,
    pub repo: Repo,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct PullRequest {
    pub title: String,
    pub number: u32,
    pub html_url: String,
    pub state: String,
    pub user: User,
    pub merged: Option<bool>,
    pub merge_commit_sha: Option<String>,
    pub assignees: Vec<User>,
    pub head: BranchRef,
    pub base: BranchRef,
}

impl PullRequest {
    pub fn is_merged(&self) -> bool {
        self.merged.unwrap_or(false)
    }
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct Issue {
    pub html_url: String,
    pub title: String,
    pub user: User,
    pub assignees: Vec<User>,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct Label {
    pub name: String,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct Review {
    pub state: String,
    pub body: Option<String>,
    pub html_url: String,
    pub user: User,
}

impl Review {
    pub fn body(&self) -> &str {
        match self.body {
            Some(ref body) => body,
            None => "",
        }
    }
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct Comment {
    pub commit_id: Option<String>,
    pub path: Option<String>,
    pub body: Option<String>,
    pub html_url: String,
    pub user: User,
}

impl Comment {
    pub fn body(&self) -> &str {
        match self.body {
            Some(ref body) => body,
            None => "",
        }
    }
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct Commit {
    pub id: String,
    pub tree_id: String,
    pub message: String,
    pub url: String,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct AssignResponse {
    pub assignees: Vec<User>,
}

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

    #[test]
    fn test_repo_parse() {
        // note: trailing slash should'nt bother it
        let repo = Repo::parse("http://git.company.com/users/repo/").unwrap();

        assert_eq!("http://git.company.com/users/repo/", repo.html_url);
        assert_eq!("users/repo", repo.full_name);
        assert_eq!("users", repo.owner.login());
    }

    #[test]
    #[should_panic]
    fn test_repo_parse_no_repo() {
        Repo::parse("http://git.company.com/users/").unwrap();
    }

    #[test]
    #[should_panic]
    fn test_repo_parse_no_user() {
        Repo::parse("http://git.company.com/").unwrap();
    }

    #[test]
    #[should_panic]
    fn test_repo_parse_too_many_parts() {
        Repo::parse("http://git.company.com/users/repo/huh").unwrap();
    }

    #[test]
    fn test_hook_body_funcs() {
        // test defaults
        {
            let body = HookBody::new();
            assert_eq!("", body.ref_name());
            assert_eq!("", body.after());
            assert_eq!("", body.before());
            assert_eq!(false, body.forced());
            assert_eq!(false, body.created());
            assert_eq!(false, body.deleted());
        }

        // test values
        {
            let mut body = HookBody::new();
            body.ref_name = Some("the-ref".to_string());
            body.after = Some("after".to_string());
            body.before = Some("before".to_string());
            assert_eq!("the-ref", body.ref_name());
            assert_eq!("after", body.after());
            assert_eq!("before", body.before());
        }
        // test bools one by one
        {
            let mut body = HookBody::new();
            body.forced = Some(true);
            assert_eq!(true, body.forced());
        }

        {
            let mut body = HookBody::new();
            body.created = Some(true);
            assert_eq!(true, body.created());
        }
        {
            let mut body = HookBody::new();
            body.deleted = Some(true);
            assert_eq!(true, body.deleted());
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

extern crate wayland_client;
use wayland_client::client::{FromPrimitive, Display,
                             Registry, RegistryEventHandler,
                             Seat, SeatEventHandler, SeatCapability,
                             Shm, ShmEventHandler, ShmFormat,
                             Output, OutputEventHandler, OutputSubpixel,
                             OutputTransform, OutputMode};

use std::collections::HashMap;

#[derive(Default)]
struct SeatData {
    name: String,
    capabilities: Vec<String>,
}

#[derive(Default)]
struct ShmData {
    formats: Vec<String>,
}

#[derive(Default)]
struct OutputData {
    x: i32,
    y: i32,
    physical_width: i32,
    physical_height: i32,
    subpixel: String,
    make: String,
    model: String,
    transform: String,
    modes: Vec<OutputModeData>,
}

struct OutputModeData {
    width: i32,
    height: i32,
    refresh: i32,
    flags: String,
}

struct Info {
    registry: Registry,
    seat: Option<Seat>,
    shm: Option<Shm>,
    output: Option<Output>,
    pub roundtrip: bool,
    data: HashMap<String, String>,
    seat_data: SeatData,
    shm_data: ShmData,
    output_data: OutputData,
}

impl Info {
    fn new(registry: Registry) -> Info {
        return Info {
            registry: registry,
            seat: None,
            shm: None,
            output: None,
            roundtrip: true,
            data: HashMap::new(),
            seat_data: Default::default(),
            shm_data: Default::default(),
            output_data: Default::default(),
        };
    }
}

impl RegistryEventHandler for Info {
    fn get_registry(&mut self) -> &mut Registry {
        return &mut self.registry;
    }

    fn on_global(&mut self, name: u32, interface: String, version: u32) {
        self.data.insert(interface.clone(),
                         format!("interface: '{}', version: {}, name: {}",
                                 interface, version, name));

        if interface == "wl_seat" {
            self.roundtrip = true;
            self.seat = self.registry.bind(name, version).ok();
            SeatEventHandler::connect_dispatcher(self);
        } else if interface == "wl_shm" {
            self.roundtrip = true;
            self.shm = self.registry.bind(name, version).ok();
            ShmEventHandler::connect_dispatcher(self);
        } else if interface == "wl_output" {
            self.roundtrip = true;
            self.output = self.registry.bind(name, version).ok();
            OutputEventHandler::connect_dispatcher(self);
        }
    }
}

impl SeatEventHandler for Info {
    fn get_seat(&mut self) -> &mut Seat {
        return self.seat.as_mut().unwrap();
    }

    fn on_capabilities(&mut self, capabilities: u32) {
        println!("on_capabilities({})", capabilities);
    }

    fn on_name(&mut self, name: String) {
        println!("on_name({})", name);
    }
}

impl ShmEventHandler for Info {
    fn get_shm(&mut self) -> &mut Shm {
        return self.shm.as_mut().unwrap();
    }

    fn on_format(&mut self, format: u32) {
        println!("on_format({:?})", ShmFormat::from_u32(format).unwrap());
    }
}

impl OutputEventHandler for Info {
    fn get_output(&mut self) -> &mut Output {
        return self.output.as_mut().unwrap();
    }

    fn on_geometry(&mut self, x: i32, y: i32, physical_width: i32,
                   physical_height: i32, subpixel: i32, make: String, model:
                   String, transform: i32) {
        println!("on_geometry({}, {}, {}, {}, {:?}, {}, {}, {:?})", x, y,
            physical_width, physical_height,
            OutputSubpixel::from_u32(subpixel as u32).unwrap(), make, model,
            OutputTransform::from_u32(transform as u32).unwrap());
    }

    fn on_mode(&mut self, flags: u32, width: i32, height: i32, refresh: i32) {
        println!("on_mode({}, {}, {}, {})", flags, width, height, refresh);
    }

    fn on_done(&mut self) {
        println!("on_done()");
    }

    fn on_scale(&mut self, factor: i32) {
        println!("on_scale({})", factor);
    }
}

fn main() {
    let mut display = Display::connect(None).unwrap();
    let mut info = Info::new(display.get_registry().unwrap());
    RegistryEventHandler::connect_dispatcher(&mut info);

    while info.roundtrip {
        info.roundtrip = false;
        display.roundtrip();
    }
}
<commit_msg>weston-info: gather seat data<commit_after>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

extern crate wayland_client;
use wayland_client::client::{FromPrimitive, Display,
                             Registry, RegistryEventHandler,
                             Seat, SeatEventHandler, SeatCapability,
                             Shm, ShmEventHandler, ShmFormat,
                             Output, OutputEventHandler, OutputSubpixel,
                             OutputTransform, OutputMode};

use std::collections::HashMap;

#[derive(Default)]
struct SeatData {
    name: String,
    capabilities: Vec<String>,
}

#[derive(Default)]
struct ShmData {
    formats: Vec<String>,
}

#[derive(Default)]
struct OutputData {
    x: i32,
    y: i32,
    physical_width: i32,
    physical_height: i32,
    subpixel: String,
    make: String,
    model: String,
    transform: String,
    modes: Vec<OutputModeData>,
}

struct OutputModeData {
    width: i32,
    height: i32,
    refresh: i32,
    flags: String,
}

struct Info {
    registry: Registry,
    seat: Option<Seat>,
    shm: Option<Shm>,
    output: Option<Output>,
    pub roundtrip: bool,
    data: HashMap<String, String>,
    seat_data: SeatData,
    shm_data: ShmData,
    output_data: OutputData,
}

impl Info {
    fn new(registry: Registry) -> Info {
        return Info {
            registry: registry,
            seat: None,
            shm: None,
            output: None,
            roundtrip: true,
            data: HashMap::new(),
            seat_data: Default::default(),
            shm_data: Default::default(),
            output_data: Default::default(),
        };
    }
}

impl RegistryEventHandler for Info {
    fn get_registry(&mut self) -> &mut Registry {
        return &mut self.registry;
    }

    fn on_global(&mut self, name: u32, interface: String, version: u32) {
        self.data.insert(interface.clone(),
                         format!("interface: '{}', version: {}, name: {}",
                                 interface, version, name));

        if interface == "wl_seat" {
            self.roundtrip = true;
            self.seat = self.registry.bind(name, version).ok();
            SeatEventHandler::connect_dispatcher(self);
        } else if interface == "wl_shm" {
            self.roundtrip = true;
            self.shm = self.registry.bind(name, version).ok();
            ShmEventHandler::connect_dispatcher(self);
        } else if interface == "wl_output" {
            self.roundtrip = true;
            self.output = self.registry.bind(name, version).ok();
            OutputEventHandler::connect_dispatcher(self);
        }
    }
}

impl SeatEventHandler for Info {
    fn get_seat(&mut self) -> &mut Seat {
        return self.seat.as_mut().unwrap();
    }

    fn on_capabilities(&mut self, capabilities: u32) {
        if capabilities & (SeatCapability::Pointer as u32) != 0 {
            self.seat_data.capabilities.push("pointer".to_string());
        }
        if capabilities & (SeatCapability::Keyboard as u32) != 0 {
            self.seat_data.capabilities.push("keyboard".to_string());
        }
        if capabilities & (SeatCapability::Touch as u32) != 0 {
            self.seat_data.capabilities.push("touch".to_string());
        }
    }

    fn on_name(&mut self, name: String) {
        self.seat_data.name = name;
    }
}

impl ShmEventHandler for Info {
    fn get_shm(&mut self) -> &mut Shm {
        return self.shm.as_mut().unwrap();
    }

    fn on_format(&mut self, format: u32) {
        println!("on_format({:?})", ShmFormat::from_u32(format).unwrap());
    }
}

impl OutputEventHandler for Info {
    fn get_output(&mut self) -> &mut Output {
        return self.output.as_mut().unwrap();
    }

    fn on_geometry(&mut self, x: i32, y: i32, physical_width: i32,
                   physical_height: i32, subpixel: i32, make: String, model:
                   String, transform: i32) {
        println!("on_geometry({}, {}, {}, {}, {:?}, {}, {}, {:?})", x, y,
            physical_width, physical_height,
            OutputSubpixel::from_u32(subpixel as u32).unwrap(), make, model,
            OutputTransform::from_u32(transform as u32).unwrap());
    }

    fn on_mode(&mut self, flags: u32, width: i32, height: i32, refresh: i32) {
        println!("on_mode({}, {}, {}, {})", flags, width, height, refresh);
    }

    fn on_done(&mut self) {
        println!("on_done()");
    }

    fn on_scale(&mut self, factor: i32) {
        println!("on_scale({})", factor);
    }
}

fn main() {
    let mut display = Display::connect(None).unwrap();
    let mut info = Info::new(display.get_registry().unwrap());
    RegistryEventHandler::connect_dispatcher(&mut info);

    while info.roundtrip {
        info.roundtrip = false;
        display.roundtrip();
    }
}
<|endoftext|>


<commit_before>/// The Toml Set extensions

use toml::Value;

use tokenizer::tokenize_with_seperator;
use error::*;

pub trait TomlValueSetExt<'doc> {

    /// Extension function for setting a value in the current toml::Value document
    /// using a custom seperator
    ///
    /// # Semantics
    ///
    /// The function _never_ creates intermediate data structures (Tables or Arrays) in the
    /// document.
    ///
    /// # Return value
    ///
    /// * If the set operation worked correctly, `Ok(None)` is returned.
    /// * If the set operation replaced an existing value `Ok(Some(old_value))` is returned
    /// * On failure, `Err(e)` is returned:
    ///     * If the query is `"a.b.c"` but there is no table `"b"`: error
    ///     * If the query is `"a.b.[0]"` but "`b"` is not an array: error
    ///     * If the query is `"a.b.[3]"` but the array at "`b"` has no index `3`: error
    ///     * etc.
    ///
    fn set_with_seperator(&mut self, query: &String, sep: char, value: Value) -> Result<Option<Value>>;

    /// Extension function for setting a value from the current toml::Value document
    ///
    /// See documentation of `TomlValueSetExt::set_with_seperator`
    fn set(&mut self, query: &String, value: Value) -> Result<Option<Value>> {
        self.set_with_seperator(query, '.', value)
    }

}

impl<'doc> TomlValueSetExt<'doc> for Value {

    fn set_with_seperator(&mut self, query: &String, sep: char, value: Value) -> Result<Option<Value>> {
        use resolver::mut_resolver::resolve;

    }

}

<commit_msg>Add tests for set functionality<commit_after>/// The Toml Set extensions

use toml::Value;

use tokenizer::tokenize_with_seperator;
use error::*;

pub trait TomlValueSetExt<'doc> {

    /// Extension function for setting a value in the current toml::Value document
    /// using a custom seperator
    ///
    /// # Semantics
    ///
    /// The function _never_ creates intermediate data structures (Tables or Arrays) in the
    /// document.
    ///
    /// # Return value
    ///
    /// * If the set operation worked correctly, `Ok(None)` is returned.
    /// * If the set operation replaced an existing value `Ok(Some(old_value))` is returned
    /// * On failure, `Err(e)` is returned:
    ///     * If the query is `"a.b.c"` but there is no table `"b"`: error
    ///     * If the query is `"a.b.[0]"` but "`b"` is not an array: error
    ///     * If the query is `"a.b.[3]"` but the array at "`b"` has no index `3`: error
    ///     * etc.
    ///
    fn set_with_seperator(&mut self, query: &String, sep: char, value: Value) -> Result<Option<Value>>;

    /// Extension function for setting a value from the current toml::Value document
    ///
    /// See documentation of `TomlValueSetExt::set_with_seperator`
    fn set(&mut self, query: &String, value: Value) -> Result<Option<Value>> {
        self.set_with_seperator(query, '.', value)
    }

}

impl<'doc> TomlValueSetExt<'doc> for Value {

    fn set_with_seperator(&mut self, query: &String, sep: char, value: Value) -> Result<Option<Value>> {
        use resolver::mut_resolver::resolve;

    }

}

#[cfg(test)]
mod test {
    use super::*;
    use toml::Value;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_set_with_seperator_into_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        a = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("table.a"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("table");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Table(_)));
                match inner {
                    &Value::Table(ref t) => {
                        assert!(!t.is_empty());

                        let a = t.get("a");
                        assert!(a.is_some());

                        let a = a.unwrap();
                        assert!(is_match!(a, &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_array() {
        use std::ops::Index;

        let mut toml : Value = toml_from_str(r#"
        array = [ 0 ]
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("array.[0]"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let inner = t.get("array");
                assert!(inner.is_some());

                let inner = inner.unwrap();
                assert!(is_match!(inner, &Value::Array(_)));
                match inner {
                    &Value::Array(ref a) => {
                        assert!(!a.is_empty());
                        assert!(is_match!(a.index(0), &Value::Integer(1)));
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

    #[test]
    fn test_set_with_seperator_into_nested_table() {
        let mut toml : Value = toml_from_str(r#"
        [a.b.c]
        d = 0
        "#).unwrap();

        let res = toml.set_with_seperator(&String::from("a.b.c.d"), '.', Value::Integer(1));

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(0)));

        assert!(is_match!(toml, Value::Table(_)));
        match toml {
            Value::Table(ref t) => {
                assert!(!t.is_empty());

                let a = t.get("a");
                assert!(a.is_some());

                let a = a.unwrap();
                assert!(is_match!(a, &Value::Table(_)));
                match a {
                    &Value::Table(ref a) => {
                        assert!(!a.is_empty());

                        let b_tab = a.get("b");
                        assert!(b_tab.is_some());

                        let b_tab = b_tab.unwrap();
                        assert!(is_match!(b_tab, &Value::Table(_)));
                        match b_tab {
                            &Value::Table(ref b) => {
                                assert!(!b.is_empty());

                                let c_tab = b.get("c");
                                assert!(c_tab.is_some());

                                let c_tab = c_tab.unwrap();
                                assert!(is_match!(c_tab, &Value::Table(_)));
                                match c_tab {
                                    &Value::Table(ref c) => {
                                        assert!(!c.is_empty());

                                        let d = c.get("d");
                                        assert!(d.is_some());

                                        let d = d.unwrap();
                                        assert!(is_match!(d, &Value::Integer(1)));
                                    },
                                    _ => panic!("What just happenend?"),
                                }
                            },
                            _ => panic!("What just happenend?"),
                        }
                    },
                    _ => panic!("What just happenend?"),
                }
            },
            _ => panic!("What just happenend?"),
        }
    }

}

<|endoftext|>


<commit_before>use serial::Serial;
use timer::Timer;
use keypad::Keypad;
use gpu::GPU;
use sound::Sound;

static WRAM_SIZE: uint = 0x8000;
static ZRAM_SIZE: uint = 0x7F;

#[deriving(Eq)]
enum DMAType {
	NoDMA,
	GDMA,
	HDMA,
}

pub struct MMU {
	priv wram: ~[u8, ..WRAM_SIZE],
	priv zram: ~[u8, ..ZRAM_SIZE],
	priv hdma: [u8, ..4],
	inte: u8,
	intf: u8,
	serial: Serial,
	timer: Timer,
	keypad: Keypad,
	gpu: GPU,
	sound: Sound,
	priv hdma_status: DMAType,
	priv hdma_src: u16,
	priv hdma_dst: u16,
	priv hdma_len: u8,
	priv wrambank: u8,
	priv mbc: ~::mbc::MBC,
	priv gbmode: ::gbmode::GbMode,
}

impl MMU {
	pub fn new(romname: &str) -> MMU {
		let mut res = MMU {
			wram: ~([0, ..WRAM_SIZE]),
			zram: ~([0, ..ZRAM_SIZE]),
			hdma: [0, ..4],
			wrambank: 1,
			inte: 0,
			intf: 0,
			serial: Serial::new(),
			timer: Timer::new(),
			keypad: Keypad::new(),
			gpu: GPU::new(),
			sound: Sound::new(),
			mbc: ::mbc::get_mbc(&Path::new(romname)),
			gbmode: ::gbmode::Classic,
			hdma_src: 0,
			hdma_dst: 0,
			hdma_status: NoDMA,
			hdma_len: 0xFF,
		};
		if res.rb(0x0143) == 0xC0 {
			fail!("This game does not work in Classic mode");
		}
		res.set_initial();
		return res
	}

	pub fn new_cgb(romname: &str) -> MMU {
		let mut res = MMU {
			wram: ~([0,.. WRAM_SIZE]),
			zram: ~([0,.. ZRAM_SIZE]),
			wrambank: 1,
			hdma: [0,.. 4],
			inte: 0,
			intf: 0,
			serial: Serial::new(),
			timer: Timer::new(),
			keypad: Keypad::new(),
			gpu: GPU::new_cgb(),
			sound: Sound::new(),
			mbc: ::mbc::get_mbc(&Path::new(romname)),
			gbmode: ::gbmode::Color,
			hdma_src: 0,
			hdma_dst: 0,
			hdma_status: NoDMA,
			hdma_len: 0xFF,
		};
		res.determine_mode();
		res.set_initial();
		return res;
	}

	fn set_initial(&mut self) {
		self.wb(0xFF05, 0);
		self.wb(0xFF06, 0);
		self.wb(0xFF07, 0);
		self.wb(0xFF40, 0x91);
		self.wb(0xFF42, 0);
		self.wb(0xFF43, 0);
		self.wb(0xFF45, 0);
		self.wb(0xFF47, 0xFC);
		self.wb(0xFF48, 0xFF);
		self.wb(0xFF49, 0xFF);
		self.wb(0xFF4A, 0);
		self.wb(0xFF4B, 0);
	}

	fn determine_mode(&mut self) {
		let mode = match self.rb(0x0143) & 0x80 {
			0x80 => ::gbmode::Color,
			_ => ::gbmode::ColorAsClassic,
		};
		self.gbmode = mode;
		self.gpu.gbmode = mode;
	}

	pub fn get_mode(&self) -> ::gbmode::GbMode {
		self.gbmode
	}

	pub fn cycle(&mut self, cputicks: uint) -> uint {
		let ticks = cputicks + self.perform_hdma();

		self.timer.cycle(ticks);
		self.intf |= self.timer.interrupt;
		self.timer.interrupt = 0;

		self.intf |= self.keypad.interrupt;
		self.keypad.interrupt = 0;

		self.gpu.cycle(ticks);
		self.intf |= self.gpu.interrupt;
		self.gpu.interrupt = 0;

		return ticks;
	}

	pub fn rb(&self, address: u16) -> u8 {
		match address {
			0x0000 .. 0x7FFF => self.mbc.readrom(address),
			0x8000 .. 0x9FFF => self.gpu.rb(address),
			0xA000 .. 0xBFFF => self.mbc.readram(address),
			0xC000 .. 0xCFFF | 0xE000 .. 0xEFFF => self.wram[address & 0x0FFF],
			0xD000 .. 0xDFFF | 0xF000 .. 0xFDFF => self.wram[(self.wrambank as u16 * 0x1000) | address & 0x0FFF],
			0xFE00 .. 0xFE9F => self.gpu.rb(address),
			0xFF00 => self.keypad.rb(),
			0xFF01 .. 0xFF02 => self.serial.rb(address),
			0xFF04 .. 0xFF07 => self.timer.rb(address),
			0xFF0F => self.intf,
			0xFF10 .. 0xFF26 => self.sound.rb(address),
			0xFF4D => 0,
			0xFF40 .. 0xFF4F => self.gpu.rb(address),
			0xFF51 .. 0xFF55 => self.hdma_read(address),
			0xFF68 .. 0xFF6B => self.gpu.rb(address),
			0xFF70 => self.wrambank,
			0xFF80 .. 0xFFFE => self.zram[address & 0x007F],
			0xFFFF => self.inte,
			_ => { warn!("rb not implemented for {:X}", address); 0 },
		}
	}

	pub fn rw(&self, address: u16) -> u16 {
		(self.rb(address) as u16) | (self.rb(address + 1) as u16 << 8)
	}

	pub fn wb(&mut self, address: u16, value: u8) {
		match address {
			0x0000 .. 0x7FFF => self.mbc.writerom(address, value),
			0x8000 .. 0x9FFF => self.gpu.wb(address, value),
			0xA000 .. 0xBFFF => self.mbc.writeram(address, value),
			0xC000 .. 0xCFFF | 0xE000 .. 0xEFFF => self.wram[address & 0x0FFF] = value,
			0xD000 .. 0xDFFF | 0xF000 .. 0xFDFF => self.wram[(self.wrambank as u16 * 0x1000) | address & 0x0FFF] = value,
			0xFE00 .. 0xFE9F => self.gpu.wb(address, value),
			0xFF00 => self.keypad.wb(value),
			0xFF01 .. 0xFF02 => self.serial.wb(address, value),
			0xFF04 .. 0xFF07 => self.timer.wb(address, value),
			0xFF10 .. 0xFF26 => self.sound.wb(address, value),
			0xFF46 => self.oamdma(value),
			0xFF4D => { if value & 0x1 == 0x1 { fail!("Speed switch requested but not supported"); } }, // CGB speed switch
			0xFF40 .. 0xFF4F => self.gpu.wb(address, value),
			0xFF51 .. 0xFF55 => self.hdma_write(address, value),
			0xFF68 .. 0xFF6B => self.gpu.wb(address, value),
			0xFF0F => self.intf = value,
			0xFF70 => { self.wrambank = match value & 0x7 { 0 => 1, n => n }; },
			0xFF80 .. 0xFFFE => self.zram[address & 0x007F] = value,
			0xFFFF => self.inte = value,
			_ => warn!("wb not implemented for {:X}", address),
		};
	}

	pub fn ww(&mut self, address: u16, value: u16) {
		self.wb(address, (value & 0xFF) as u8);
		self.wb(address + 1, (value >> 8) as u8);
	}

	fn oamdma(&mut self, value: u8) {
		let base = (value as u16) << 8;
		for i in range(0u16, 0xA0) {
			let b = self.rb(base + i);
			self.wb(0xFE00 + i, b);
		}
	}

	fn hdma_read(&self, a: u16) -> u8 {
		match a {
			0xFF51 .. 0xFF54 => { self.hdma[a - 0xFF51] },
			0xFF55 => self.hdma_len | if self.hdma_status == NoDMA { 0x80 } else { 0 },
			_ => fail!(),
		}
	}

	fn hdma_write(&mut self, a: u16, v: u8) {
		//println!("Writing 0x{:04X} = 0x{:02X}", a, v);
		match a {
			0xFF51 => self.hdma[0] = v,
			0xFF52 => self.hdma[1] = v & 0xF0,
			0xFF53 => self.hdma[2] = v & 0x1F,
			0xFF54 => self.hdma[3] = v & 0xF0,
			0xFF55 => {
				//println!("FF55: 0x{:02X}", v);
				if self.hdma_status == HDMA {
					if v & 0x80 == 0 { self.hdma_status = NoDMA; };
					return;
				}
				let src = (self.hdma[0] as u16 << 8) | (self.hdma[1] as u16);
				let dst = (self.hdma[2] as u16 << 8) | (self.hdma[3] as u16) | 0x8000;
				if !(src <= 0x7FF0 || (src >= 0xA000 && src <= 0xDFF0)) { fail!("HDMA transfer with illegal start address {:04X}", src); }

				self.hdma_src = src;
				self.hdma_dst = dst;
				self.hdma_len = v & 0x7F;

				self.hdma_status =
					if v == 0x7F { NoDMA }
					else if v & 0x80 == 0x80 { HDMA }
					else { GDMA };
				//println!("New status: {}", match self.hdma_status { NoDMA => "NoDMA", GDMA => "GDMA", HDMA => "HDMA" });
			},
			_ => fail!(),
		};
	}

	fn perform_hdma(&mut self) -> uint {
		let len: uint = match self.hdma_status {
			NoDMA => 0,
			GDMA => self.hdma_len as uint + 1,
			HDMA => if self.gpu.may_hdma() { 1 } else { 0 },
		};

		'i: for _i in range(0, len) {
			for j in range(0u16, 16) {
				let b: u8 = self.rb(self.hdma_src + j);
				self.gpu.wb(self.hdma_dst + j, b);
			}
			self.hdma_src += 0x10;
			self.hdma_dst += 0x10;
			self.hdma_len -= 1;
			if self.hdma_len == 0xFF {
				self.hdma_status = NoDMA;
				break 'i;
			}
		}

		if len > 0 {
			(len * 16) + 1
		} else {
			0
		}
	}
}
<commit_msg>Do not fail when speed switching, but issue a warning<commit_after>use serial::Serial;
use timer::Timer;
use keypad::Keypad;
use gpu::GPU;
use sound::Sound;

static WRAM_SIZE: uint = 0x8000;
static ZRAM_SIZE: uint = 0x7F;

#[deriving(Eq)]
enum DMAType {
	NoDMA,
	GDMA,
	HDMA,
}

pub struct MMU {
	priv wram: ~[u8, ..WRAM_SIZE],
	priv zram: ~[u8, ..ZRAM_SIZE],
	priv hdma: [u8, ..4],
	inte: u8,
	intf: u8,
	serial: Serial,
	timer: Timer,
	keypad: Keypad,
	gpu: GPU,
	sound: Sound,
	priv hdma_status: DMAType,
	priv hdma_src: u16,
	priv hdma_dst: u16,
	priv hdma_len: u8,
	priv wrambank: u8,
	priv mbc: ~::mbc::MBC,
	priv gbmode: ::gbmode::GbMode,
}

impl MMU {
	pub fn new(romname: &str) -> MMU {
		let mut res = MMU {
			wram: ~([0, ..WRAM_SIZE]),
			zram: ~([0, ..ZRAM_SIZE]),
			hdma: [0, ..4],
			wrambank: 1,
			inte: 0,
			intf: 0,
			serial: Serial::new(),
			timer: Timer::new(),
			keypad: Keypad::new(),
			gpu: GPU::new(),
			sound: Sound::new(),
			mbc: ::mbc::get_mbc(&Path::new(romname)),
			gbmode: ::gbmode::Classic,
			hdma_src: 0,
			hdma_dst: 0,
			hdma_status: NoDMA,
			hdma_len: 0xFF,
		};
		if res.rb(0x0143) == 0xC0 {
			fail!("This game does not work in Classic mode");
		}
		res.set_initial();
		return res
	}

	pub fn new_cgb(romname: &str) -> MMU {
		let mut res = MMU {
			wram: ~([0,.. WRAM_SIZE]),
			zram: ~([0,.. ZRAM_SIZE]),
			wrambank: 1,
			hdma: [0,.. 4],
			inte: 0,
			intf: 0,
			serial: Serial::new(),
			timer: Timer::new(),
			keypad: Keypad::new(),
			gpu: GPU::new_cgb(),
			sound: Sound::new(),
			mbc: ::mbc::get_mbc(&Path::new(romname)),
			gbmode: ::gbmode::Color,
			hdma_src: 0,
			hdma_dst: 0,
			hdma_status: NoDMA,
			hdma_len: 0xFF,
		};
		res.determine_mode();
		res.set_initial();
		return res;
	}

	fn set_initial(&mut self) {
		self.wb(0xFF05, 0);
		self.wb(0xFF06, 0);
		self.wb(0xFF07, 0);
		self.wb(0xFF40, 0x91);
		self.wb(0xFF42, 0);
		self.wb(0xFF43, 0);
		self.wb(0xFF45, 0);
		self.wb(0xFF47, 0xFC);
		self.wb(0xFF48, 0xFF);
		self.wb(0xFF49, 0xFF);
		self.wb(0xFF4A, 0);
		self.wb(0xFF4B, 0);
	}

	fn determine_mode(&mut self) {
		let mode = match self.rb(0x0143) & 0x80 {
			0x80 => ::gbmode::Color,
			_ => ::gbmode::ColorAsClassic,
		};
		self.gbmode = mode;
		self.gpu.gbmode = mode;
	}

	pub fn get_mode(&self) -> ::gbmode::GbMode {
		self.gbmode
	}

	pub fn cycle(&mut self, cputicks: uint) -> uint {
		let ticks = cputicks + self.perform_hdma();

		self.timer.cycle(ticks);
		self.intf |= self.timer.interrupt;
		self.timer.interrupt = 0;

		self.intf |= self.keypad.interrupt;
		self.keypad.interrupt = 0;

		self.gpu.cycle(ticks);
		self.intf |= self.gpu.interrupt;
		self.gpu.interrupt = 0;

		return ticks;
	}

	pub fn rb(&self, address: u16) -> u8 {
		match address {
			0x0000 .. 0x7FFF => self.mbc.readrom(address),
			0x8000 .. 0x9FFF => self.gpu.rb(address),
			0xA000 .. 0xBFFF => self.mbc.readram(address),
			0xC000 .. 0xCFFF | 0xE000 .. 0xEFFF => self.wram[address & 0x0FFF],
			0xD000 .. 0xDFFF | 0xF000 .. 0xFDFF => self.wram[(self.wrambank as u16 * 0x1000) | address & 0x0FFF],
			0xFE00 .. 0xFE9F => self.gpu.rb(address),
			0xFF00 => self.keypad.rb(),
			0xFF01 .. 0xFF02 => self.serial.rb(address),
			0xFF04 .. 0xFF07 => self.timer.rb(address),
			0xFF0F => self.intf,
			0xFF10 .. 0xFF26 => self.sound.rb(address),
			0xFF4D => 0,
			0xFF40 .. 0xFF4F => self.gpu.rb(address),
			0xFF51 .. 0xFF55 => self.hdma_read(address),
			0xFF68 .. 0xFF6B => self.gpu.rb(address),
			0xFF70 => self.wrambank,
			0xFF80 .. 0xFFFE => self.zram[address & 0x007F],
			0xFFFF => self.inte,
			_ => { warn!("rb not implemented for {:X}", address); 0 },
		}
	}

	pub fn rw(&self, address: u16) -> u16 {
		(self.rb(address) as u16) | (self.rb(address + 1) as u16 << 8)
	}

	pub fn wb(&mut self, address: u16, value: u8) {
		match address {
			0x0000 .. 0x7FFF => self.mbc.writerom(address, value),
			0x8000 .. 0x9FFF => self.gpu.wb(address, value),
			0xA000 .. 0xBFFF => self.mbc.writeram(address, value),
			0xC000 .. 0xCFFF | 0xE000 .. 0xEFFF => self.wram[address & 0x0FFF] = value,
			0xD000 .. 0xDFFF | 0xF000 .. 0xFDFF => self.wram[(self.wrambank as u16 * 0x1000) | address & 0x0FFF] = value,
			0xFE00 .. 0xFE9F => self.gpu.wb(address, value),
			0xFF00 => self.keypad.wb(value),
			0xFF01 .. 0xFF02 => self.serial.wb(address, value),
			0xFF04 .. 0xFF07 => self.timer.wb(address, value),
			0xFF10 .. 0xFF26 => self.sound.wb(address, value),
			0xFF46 => self.oamdma(value),
			0xFF4D => { if value & 0x1 == 0x1 { warn!("Speed switch requested but not supported"); } }, // CGB speed switch
			0xFF40 .. 0xFF4F => self.gpu.wb(address, value),
			0xFF51 .. 0xFF55 => self.hdma_write(address, value),
			0xFF68 .. 0xFF6B => self.gpu.wb(address, value),
			0xFF0F => self.intf = value,
			0xFF70 => { self.wrambank = match value & 0x7 { 0 => 1, n => n }; },
			0xFF80 .. 0xFFFE => self.zram[address & 0x007F] = value,
			0xFFFF => self.inte = value,
			_ => warn!("wb not implemented for {:X}", address),
		};
	}

	pub fn ww(&mut self, address: u16, value: u16) {
		self.wb(address, (value & 0xFF) as u8);
		self.wb(address + 1, (value >> 8) as u8);
	}

	fn oamdma(&mut self, value: u8) {
		let base = (value as u16) << 8;
		for i in range(0u16, 0xA0) {
			let b = self.rb(base + i);
			self.wb(0xFE00 + i, b);
		}
	}

	fn hdma_read(&self, a: u16) -> u8 {
		match a {
			0xFF51 .. 0xFF54 => { self.hdma[a - 0xFF51] },
			0xFF55 => self.hdma_len | if self.hdma_status == NoDMA { 0x80 } else { 0 },
			_ => fail!(),
		}
	}

	fn hdma_write(&mut self, a: u16, v: u8) {
		//println!("Writing 0x{:04X} = 0x{:02X}", a, v);
		match a {
			0xFF51 => self.hdma[0] = v,
			0xFF52 => self.hdma[1] = v & 0xF0,
			0xFF53 => self.hdma[2] = v & 0x1F,
			0xFF54 => self.hdma[3] = v & 0xF0,
			0xFF55 => {
				//println!("FF55: 0x{:02X}", v);
				if self.hdma_status == HDMA {
					if v & 0x80 == 0 { self.hdma_status = NoDMA; };
					return;
				}
				let src = (self.hdma[0] as u16 << 8) | (self.hdma[1] as u16);
				let dst = (self.hdma[2] as u16 << 8) | (self.hdma[3] as u16) | 0x8000;
				if !(src <= 0x7FF0 || (src >= 0xA000 && src <= 0xDFF0)) { fail!("HDMA transfer with illegal start address {:04X}", src); }

				self.hdma_src = src;
				self.hdma_dst = dst;
				self.hdma_len = v & 0x7F;

				self.hdma_status =
					if v == 0x7F { NoDMA }
					else if v & 0x80 == 0x80 { HDMA }
					else { GDMA };
				//println!("New status: {}", match self.hdma_status { NoDMA => "NoDMA", GDMA => "GDMA", HDMA => "HDMA" });
			},
			_ => fail!(),
		};
	}

	fn perform_hdma(&mut self) -> uint {
		let len: uint = match self.hdma_status {
			NoDMA => 0,
			GDMA => self.hdma_len as uint + 1,
			HDMA => if self.gpu.may_hdma() { 1 } else { 0 },
		};

		'i: for _i in range(0, len) {
			for j in range(0u16, 16) {
				let b: u8 = self.rb(self.hdma_src + j);
				self.gpu.wb(self.hdma_dst + j, b);
			}
			self.hdma_src += 0x10;
			self.hdma_dst += 0x10;
			self.hdma_len -= 1;
			if self.hdma_len == 0xFF {
				self.hdma_status = NoDMA;
				break 'i;
			}
		}

		if len > 0 {
			(len * 16) + 1
		} else {
			0
		}
	}
}
<|endoftext|>


<commit_before>//! The AWS SQS API.

#![cfg_attr(feature = "nightly-testing", allow(while_let_loop))]

include!(concat!(env!("OUT_DIR"), "/sqs.rs"));

#[cfg(test)]
mod test {
    use std::collections::HashMap;
    use sqs::{SqsClient, SendMessageRequest, ReceiveMessageRequest, MessageAttributeValue};

    use super::super::{Region, SignedRequest};
    use super::super::mock::*;

    extern crate env_logger;

    #[test]
    fn should_serialize_map_parameters_in_query_string() {
        let mock = MockRequestDispatcher::with_status(200)
            .with_body(r#"<?xml version="1.0" encoding="UTF-8"?>
            <SendMessageResponse>
              <SendMessageResult>
                  <MD5OfMessageBody>
                      fafb00f5732ab283681e124bf8747ed1
                  </MD5OfMessageBody>
                  <MD5OfMessageAttributes>
                3ae8f24a165a8cedc005670c81a27295
                  </MD5OfMessageAttributes>
                  <MessageId>
                      5fea7756-0ea4-451a-a703-a558b933e274
                  </MessageId>
              </SendMessageResult>
              <ResponseMetadata>
                  <RequestId>
                      27daac76-34dd-47df-bd01-1f6e873584a0
                  </RequestId>
              </ResponseMetadata>
            </SendMessageResponse>"#)
            .with_request_checker(|request: &SignedRequest| {
                assert_eq!("POST", request.method);
                assert_eq!("/", request.path);
                assert_eq!(None, request.payload);
                assert_eq!(Some(&Some("test_attribute_name".to_owned())),
                           request.params.get("MessageAttribute.1.Name"));
                assert_eq!(Some(&Some("test_attribute_value".to_owned())),
                           request.params.get("MessageAttribute.1.Value.StringValue"));
                assert_eq!(Some(&Some("String".to_owned())),
                           request.params.get("MessageAttribute.1.Value.DataType"));
            });

        let mut message_attributes = HashMap::new();

        message_attributes.insert("test_attribute_name".to_owned(),
                                  MessageAttributeValue {
                                      string_value: Some("test_attribute_value".to_owned()),
                                      data_type: "String".to_owned(),
                                      ..Default::default()
                                  });
        let request = SendMessageRequest {
            message_body: "foo".to_owned(),
            queue_url: "bar".to_owned(),
            message_attributes: Some(message_attributes),
            ..Default::default()
        };

        let client =
            SqsClient::new(mock, MockCredentialsProvider, Region::UsEast1);
        let _result = client.send_message(&request).unwrap();
    }

    #[test]
    fn should_fix_issue_323() {
        let mock = MockRequestDispatcher::with_status(200)
            .with_body(r#"<?xml version="1.0" encoding="UTF-8"?>
            <ReceiveMessageResponse>
              <ReceiveMessageResult>
                <Message>
                  <MessageId>
                    5fea7756-0ea4-451a-a703-a558b933e274
                  </MessageId>
                  <ReceiptHandle>
                    MbZj6wDWli+JvwwJaBV+3dcjk2YW2vA3+STFFljTM8tJJg6HRG6PYSasuWXPJB+Cw
                    Lj1FjgXUv1uSj1gUPAWV66FU/WeR4mq2OKpEGYWbnLmpRCJVAyeMjeU5ZBdtcQ+QE
                    auMZc8ZRv37sIW2iJKq3M9MFx1YvV11A2x/KSbkJ0=
                  </ReceiptHandle>
                  <MD5OfBody>
                    fafb00f5732ab283681e124bf8747ed1
                  </MD5OfBody>
                  This is a test message
                  <Attribute>
                    <Name>SenderId</Name>
                    <Value>195004372649</Value>
                  </Attribute>
                </Message>
              </ReceiveMessageResult>
              <ResponseMetadata>
                <RequestId>
                  b6633655-283d-45b4-aee4-4e84e0ae6afa
                </RequestId>
              </ResponseMetadata>
          </ReceiveMessageResponse>"#)
            .with_request_checker(|request: &SignedRequest| {
                assert_eq!("POST", request.method);
                assert_eq!("/", request.path);
                assert_eq!(request.params.get("Action"), Some(&Some("ReceiveMessage".to_owned())));
                assert_eq!(request.params.get("MaxNumberOfMessages"), Some(&Some("1".to_owned())));
                assert_eq!(request.params.get("VisibilityTimeout"), Some(&Some("2".to_owned())));
                assert_eq!(request.params.get("WaitTimeSeconds"), Some(&Some("3".to_owned())));
                assert_eq!(request.params.get("Integer"), None);
            });

        let request = ReceiveMessageRequest {
          max_number_of_messages: Some(1),
          queue_url: "foo".to_owned(),
          visibility_timeout: Some(2),
          wait_time_seconds: Some(3),
            ..Default::default()
        };

        let client = SqsClient::with_request_dispatcher(mock, MockCredentialsProvider, Region::UsEast1);
        let _result = client.receive_message(&request).unwrap();
    }
}
<commit_msg>Catches straggler integration test.<commit_after>//! The AWS SQS API.

#![cfg_attr(feature = "nightly-testing", allow(while_let_loop))]

include!(concat!(env!("OUT_DIR"), "/sqs.rs"));

#[cfg(test)]
mod test {
    use std::collections::HashMap;
    use sqs::{SqsClient, SendMessageRequest, ReceiveMessageRequest, MessageAttributeValue};

    use super::super::{Region, SignedRequest};
    use super::super::mock::*;

    extern crate env_logger;

    #[test]
    fn should_serialize_map_parameters_in_query_string() {
        let mock = MockRequestDispatcher::with_status(200)
            .with_body(r#"<?xml version="1.0" encoding="UTF-8"?>
            <SendMessageResponse>
              <SendMessageResult>
                  <MD5OfMessageBody>
                      fafb00f5732ab283681e124bf8747ed1
                  </MD5OfMessageBody>
                  <MD5OfMessageAttributes>
                3ae8f24a165a8cedc005670c81a27295
                  </MD5OfMessageAttributes>
                  <MessageId>
                      5fea7756-0ea4-451a-a703-a558b933e274
                  </MessageId>
              </SendMessageResult>
              <ResponseMetadata>
                  <RequestId>
                      27daac76-34dd-47df-bd01-1f6e873584a0
                  </RequestId>
              </ResponseMetadata>
            </SendMessageResponse>"#)
            .with_request_checker(|request: &SignedRequest| {
                assert_eq!("POST", request.method);
                assert_eq!("/", request.path);
                assert_eq!(None, request.payload);
                assert_eq!(Some(&Some("test_attribute_name".to_owned())),
                           request.params.get("MessageAttribute.1.Name"));
                assert_eq!(Some(&Some("test_attribute_value".to_owned())),
                           request.params.get("MessageAttribute.1.Value.StringValue"));
                assert_eq!(Some(&Some("String".to_owned())),
                           request.params.get("MessageAttribute.1.Value.DataType"));
            });

        let mut message_attributes = HashMap::new();

        message_attributes.insert("test_attribute_name".to_owned(),
                                  MessageAttributeValue {
                                      string_value: Some("test_attribute_value".to_owned()),
                                      data_type: "String".to_owned(),
                                      ..Default::default()
                                  });
        let request = SendMessageRequest {
            message_body: "foo".to_owned(),
            queue_url: "bar".to_owned(),
            message_attributes: Some(message_attributes),
            ..Default::default()
        };

        let client =
            SqsClient::new(mock, MockCredentialsProvider, Region::UsEast1);
        let _result = client.send_message(&request).unwrap();
    }

    #[test]
    fn should_fix_issue_323() {
        let mock = MockRequestDispatcher::with_status(200)
            .with_body(r#"<?xml version="1.0" encoding="UTF-8"?>
            <ReceiveMessageResponse>
              <ReceiveMessageResult>
                <Message>
                  <MessageId>
                    5fea7756-0ea4-451a-a703-a558b933e274
                  </MessageId>
                  <ReceiptHandle>
                    MbZj6wDWli+JvwwJaBV+3dcjk2YW2vA3+STFFljTM8tJJg6HRG6PYSasuWXPJB+Cw
                    Lj1FjgXUv1uSj1gUPAWV66FU/WeR4mq2OKpEGYWbnLmpRCJVAyeMjeU5ZBdtcQ+QE
                    auMZc8ZRv37sIW2iJKq3M9MFx1YvV11A2x/KSbkJ0=
                  </ReceiptHandle>
                  <MD5OfBody>
                    fafb00f5732ab283681e124bf8747ed1
                  </MD5OfBody>
                  This is a test message
                  <Attribute>
                    <Name>SenderId</Name>
                    <Value>195004372649</Value>
                  </Attribute>
                </Message>
              </ReceiveMessageResult>
              <ResponseMetadata>
                <RequestId>
                  b6633655-283d-45b4-aee4-4e84e0ae6afa
                </RequestId>
              </ResponseMetadata>
          </ReceiveMessageResponse>"#)
            .with_request_checker(|request: &SignedRequest| {
                assert_eq!("POST", request.method);
                assert_eq!("/", request.path);
                assert_eq!(request.params.get("Action"), Some(&Some("ReceiveMessage".to_owned())));
                assert_eq!(request.params.get("MaxNumberOfMessages"), Some(&Some("1".to_owned())));
                assert_eq!(request.params.get("VisibilityTimeout"), Some(&Some("2".to_owned())));
                assert_eq!(request.params.get("WaitTimeSeconds"), Some(&Some("3".to_owned())));
                assert_eq!(request.params.get("Integer"), None);
            });

        let request = ReceiveMessageRequest {
          max_number_of_messages: Some(1),
          queue_url: "foo".to_owned(),
          visibility_timeout: Some(2),
          wait_time_seconds: Some(3),
            ..Default::default()
        };

        let client = SqsClient::new(mock, MockCredentialsProvider, Region::UsEast1);
        let _result = client.receive_message(&request).unwrap();
    }
}
<|endoftext|>


<commit_before>use syntax::ast;
use syntax::parse::token;

pub use expr::ExprBuilder;
pub use ident::ToIdent;
pub use name::ToName;
pub use path::PathBuilder;

//////////////////////////////////////////////////////////////////////////////

pub trait ToInternedString {
    fn to_interned_string(&self) -> token::InternedString;
}

impl ToInternedString for token::InternedString {
    fn to_interned_string(&self) -> token::InternedString {
        self.clone()
    }
}

impl<'a> ToInternedString for &'a str {
    fn to_interned_string(&self) -> token::InternedString {
        token::intern_and_get_ident(self)
    }
}

impl ToInternedString for ast::Ident {
    fn to_interned_string(&self) -> token::InternedString {
        self.name.as_str()
    }
}

impl ToInternedString for ast::Name {
    fn to_interned_string(&self) -> token::InternedString {
        self.as_str()
    }
}

impl<'a, T> ToInternedString for &'a T where T: ToInternedString {
    fn to_interned_string(&self) -> token::InternedString {
        (**self).to_interned_string()
    }
}
<commit_msg>Stop re-exporting from aster::str<commit_after>use syntax::ast;
use syntax::parse::token;

//////////////////////////////////////////////////////////////////////////////

pub trait ToInternedString {
    fn to_interned_string(&self) -> token::InternedString;
}

impl ToInternedString for token::InternedString {
    fn to_interned_string(&self) -> token::InternedString {
        self.clone()
    }
}

impl<'a> ToInternedString for &'a str {
    fn to_interned_string(&self) -> token::InternedString {
        token::intern_and_get_ident(self)
    }
}

impl ToInternedString for ast::Ident {
    fn to_interned_string(&self) -> token::InternedString {
        self.name.as_str()
    }
}

impl ToInternedString for ast::Name {
    fn to_interned_string(&self) -> token::InternedString {
        self.as_str()
    }
}

impl<'a, T> ToInternedString for &'a T where T: ToInternedString {
    fn to_interned_string(&self) -> token::InternedString {
        (**self).to_interned_string()
    }
}
<|endoftext|>


<commit_before>use std::{default, iter, fmt};
use std::collections::LinkedList;

use super::c_simple;
use super::c_simple::{CAST, CASTNode};
use frontend::radeco_containers::RadecoFunction;
use petgraph::graph::{Graph, NodeIndex, EdgeIndex, Edges, EdgeReference};
use petgraph::visit::EdgeRef;
use petgraph::{EdgeDirection, Direction, Directed};

#[derive(Debug, Clone, PartialEq)]
enum SimpleCASTNode {
    Action(ActionNode),
    Value(ValueNode),
}

#[derive(Debug, Clone, PartialEq)]
enum ActionNode {
    Assignment,
    Call(String),
    Return,
    If,
    Goto,
}

// TODO
#[derive(Debug, Clone, PartialEq)]
enum ValueNode {
    /// The string is the name of variable
    Variable(String),
    Constant,
}

#[derive(Debug, Clone, PartialEq)]
enum SimpleCASTEdge {
    Action(ActionEdge),
    Value(ValueEdge),
}

#[derive(Debug, Clone, PartialEq)]
enum ActionEdge {
    IfThen,
    IfElse,
    FuncCall,
    FuncRet,
    Normal,
}

#[derive(Debug, Clone, PartialEq)]
enum ValueEdge {
    AssignSrc,
    AssignDst,
    Arg(u8),
    GotoDst,
}

struct SimpleCAST {
    /// Name of function of this AST
    fname: String,
    entry: NodeIndex,
    ast: Graph<SimpleCASTNode, SimpleCASTEdge>,
}

impl SimpleCASTNode {
    fn is_exit(&self) -> bool {
        match self {
            &SimpleCASTNode::Action(ActionNode::Return) => true,
            _ => false,
        }
    }
}

/// Returns nodes which is connected with given type of edge
fn neighbors_by_edge(edges: &Vec<EdgeReference<SimpleCASTEdge>>, ty: &SimpleCASTEdge) -> Vec<NodeIndex> {
    edges.iter().filter(|e| (*e).weight() == ty)
        .map(|e| e.target())
        .collect()
}

impl SimpleCAST {

    fn next_actions(&self, idx: NodeIndex) -> Vec<NodeIndex> {
        self.ast.edges_directed(idx, Direction::Outgoing)
            .into_iter()
            .filter_map(|e| {
                match e.weight() {
                    &SimpleCASTEdge::Action(_) => Some(e.target()),
                    _ => None,
                }
            }).collect()
    }

    /// Returns a pair (IfThen, IfElse)
    fn branch(&self, idx: NodeIndex) -> Option<(NodeIndex, Option<NodeIndex>)> {
        if self.ast.node_weight(idx) != Some(&SimpleCASTNode::Action(ActionNode::If)) {
            return None;
        }
        let ns = self.ast.edges_directed(idx, Direction::Outgoing).into_iter().collect();
        let if_then = neighbors_by_edge(&ns, &SimpleCASTEdge::Action(ActionEdge::IfThen))
            .first().map(|e| e.clone());
        let if_else = neighbors_by_edge(&ns, &SimpleCASTEdge::Action(ActionEdge::IfElse))
            .first().map(|e| e.clone());
        if if_then.is_some() {
            Some((if_then.unwrap(), if_else))
        } else {
            None
        }
    }

    /// Returns destination of goto statement
    fn goto(&self, idx: NodeIndex) -> Option<NodeIndex> {
        if self.ast.node_weight(idx) != Some(&SimpleCASTNode::Action(ActionNode::Goto))  {
            return None;
        };
        let goto_dsts = self.ast.edges_directed(idx, Direction::Outgoing)
            .into_iter()
            .filter_map(|e| {
                match e.weight() {
                    &SimpleCASTEdge::Value(ValueEdge::GotoDst) => Some(e.target()),
                    _ => None,
                }
            }).collect::<Vec<_>>();
        if goto_dsts.len() != 1 {
            radeco_warn!("Destination of Goto has more than 1 labels");
            return None;
        };
        goto_dsts.first().map(|n| n.clone())
    }

    /// Returns a pair (Dst, Src) which represents Dst = Src
    fn assignment(&self, idx: NodeIndex) -> Option<(NodeIndex, NodeIndex)> {
        if self.ast.node_weight(idx) != Some(&SimpleCASTNode::Action(ActionNode::Assignment)) {
            return None;
        }
        let ns = self.ast.edges_directed(idx, Direction::Outgoing).into_iter().collect();
        let src = neighbors_by_edge(&ns, &SimpleCASTEdge::Value(ValueEdge::AssignSrc))
            .first().map(|e| e.clone());
        let dst = neighbors_by_edge(&ns, &SimpleCASTEdge::Value(ValueEdge::AssignDst))
            .first().map(|e| e.clone());
        if src.is_some() && dst.is_some() {
            return None;
        }
        Some((dst.unwrap(), src.unwrap()))
    }

    /// Returns arguments of function call
    fn args_call(&self, idx: NodeIndex) -> Option<Vec<NodeIndex>> {
        match self.ast.node_weight(idx) {
            Some(&SimpleCASTNode::Action(ActionNode::Call(_))) => {},
            _ => {return None;},
        };
        let mut args = self.ast.edges_directed(idx, Direction::Outgoing)
            .into_iter()
            .filter_map(|e| {
                match e.weight() {
                    &SimpleCASTEdge::Value(ValueEdge::Arg(o)) => Some((o, e.target())),
                    _ => None,
                }
            }).collect::<Vec<_>>();
        args.sort_by_key(|k| k.0);
        let ret = args.into_iter()
            .map(|(_, b)| b)
            .collect();
        Some(ret)
    }

    fn to_c_ast(&self) -> CAST {
        let mut c_ast = CAST::new(&self.fname);
        let mut queue = LinkedList::new();
        queue.push_back(self.entry);
        while let Some(current_node) = queue.pop_front() {
            // XXX ?
            for n in self.next_actions(current_node) {
                queue.push_back(n);
            }
            match self.ast.node_weight(current_node) {
                Some(&SimpleCASTNode::Action(ActionNode::Assignment)) => {
                    if let Some((dst, src)) = self.assignment(current_node) {
                        // TODO insert node
                    } else {
                        // TODO
                        radeco_err!("Something wrong");
                    }
                },
                Some(&SimpleCASTNode::Action(ActionNode::Call(ref name))) => {
                    let args = self.args_call(current_node);
                    // TODO insert node, args
                },
                Some(&SimpleCASTNode::Action(ActionNode::Return)) => {
                    // TODO insert node
                },
                Some(&SimpleCASTNode::Action(ActionNode::If)) => {
                    // TODO insert node
                    if let Some((if_then, if_else)) = self.branch(current_node) {
                        // TODO
                    }
                },
                Some(&SimpleCASTNode::Action(ActionNode::Goto)) => {
                    if let Some(dst) = self.goto(current_node) {
                        // TODO insert label, gotos
                    }
                },
                _ => {},
            };
        }
        c_ast
    }

}
<commit_msg>Impl SimpleCAST to CAST converter<commit_after>use std::{default, iter, fmt};
use std::collections::{HashMap, HashSet};

use super::c_simple;
use super::c_simple::{CAST, CASTNode};
use frontend::radeco_containers::RadecoFunction;
use petgraph::graph::{Graph, NodeIndex, EdgeIndex, Edges, EdgeReference};
use petgraph::visit::EdgeRef;
use petgraph::{EdgeDirection, Direction, Directed};

#[derive(Debug, Clone, PartialEq)]
enum SimpleCASTNode {
    /// Entry node of target function
    Entry,
    Action(ActionNode),
    Value(ValueNode),
}

#[derive(Debug, Clone, PartialEq)]
enum ActionNode {
    Assignment,
    Call(String),
    Return,
    If,
    Goto,
}

// TODO Use another type instead of String
// TODO Add type information
#[derive(Debug, Clone, PartialEq)]
enum ValueNode {
    /// The string is the name of variable
    Variable(String),
    /// Constant or immidiate value
    Constant(String),
    Expression(c_simple::Expr),
}

#[derive(Debug, Clone, PartialEq)]
enum SimpleCASTEdge {
    Action(ActionEdge),
    Value(ValueEdge),
}

#[derive(Debug, Clone, PartialEq)]
enum ActionEdge {
    IfThen,
    IfElse,
    Normal,
}

#[derive(Debug, Clone, PartialEq)]
enum ValueEdge {
    /// Source Node of assignment action
    AssignSrc,
    /// Destination Node of assignment action
    AssignDst,
    /// Arguments of function call
    /// the number represents it is a nth argument
    Arg(u8),
    /// Return value of target function
    RetVal,
    /// Return value of function call
    FuncVal,
    /// Operand of expression, the number
    /// represents this is nth operand.
    Operand(u8),
    /// It points to condition of If action
    Conditional,
    /// Destination of Goto statement
    GotoDst,
}

struct SimpleCAST {
    /// Name of function of this AST
    fname: String,
    /// Entry node of this function
    pub entry: NodeIndex,
    ast: Graph<SimpleCASTNode, SimpleCASTEdge>,
    /// Variables declared in this function
    vars: HashSet<NodeIndex>,
    /// Constants declared in this function
    consts: HashSet<NodeIndex>,
    /// Expressions declared in this function
    exprs: HashSet<NodeIndex>,
    /// HashMap from SimpleCAST's node to CAST's node
    node_map: HashMap<NodeIndex, NodeIndex>,
    /// HashMap from ActionNode to label node
    label_node_map: HashMap<NodeIndex, NodeIndex>,
    /// Hashmap from label node to string it represents
    label_map: HashMap<NodeIndex, String>,
    visited: HashSet<NodeIndex>,
}

impl SimpleCASTNode {
    fn is_exit(&self) -> bool {
        match self {
            &SimpleCASTNode::Action(ActionNode::Return) => true,
            _ => false,
        }
    }
}

/// Returns nodes which is connected with given type of edge
fn neighbors_by_edge(edges: &Vec<EdgeReference<SimpleCASTEdge>>, ty: &SimpleCASTEdge) -> Vec<NodeIndex> {
    edges.iter().filter(|e| (*e).weight() == ty)
        .map(|e| e.target())
        .collect()
}

impl SimpleCAST {
    fn new(fn_name: &str) -> SimpleCAST {
        let mut ast = Graph::new();
        let entry = ast.add_node(SimpleCASTNode::Entry);
        SimpleCAST {
            fname: fn_name.to_string(),
            entry: entry,
            ast: ast,
            vars: HashSet::new(),
            consts: HashSet::new(),
            exprs: HashSet::new(),
            node_map: HashMap::new(),
            label_node_map: HashMap::new(),
            label_map: HashMap::new(),
            visited: HashSet::new(),
        }
    }

    /// Add ValueNode of variable
    fn var(&mut self, name: &str) -> NodeIndex {
        let node = self.ast.add_node(SimpleCASTNode::Value(ValueNode::Variable(name.to_string())));
        self.vars.insert(node);
        node
    }

    /// Add ValueNode of constant value
    fn constant(&mut self, name: &str) -> NodeIndex {
        let node = self.ast.add_node(SimpleCASTNode::Value(ValueNode::Constant(name.to_string())));
        self.consts.insert(node);
        node
    }

    /// Add ValueNode of expression
    fn expr(&mut self, operands: &[NodeIndex], op: c_simple::Expr) -> NodeIndex {
        let node = self.ast.add_node(SimpleCASTNode::Value(ValueNode::Expression(op)));
        for (i, operand) in operands.iter().enumerate() {
            let _ = self.ast.add_edge(node, *operand, SimpleCASTEdge::Value(ValueEdge::Operand(i as u8)));
        }
        self.exprs.insert(node);
        node
    }

    /// Add ActionNode of assignment
    fn assign(&mut self, dst: NodeIndex, src: NodeIndex, prev_action: NodeIndex) -> NodeIndex {
        let node = self.ast.add_node(SimpleCASTNode::Action(ActionNode::Assignment));
        let _ = self.ast.add_edge(node, dst, SimpleCASTEdge::Value(ValueEdge::AssignDst));
        let _ = self.ast.add_edge(node, src, SimpleCASTEdge::Value(ValueEdge::AssignSrc));
        let _ = self.ast.add_edge(prev_action, node, SimpleCASTEdge::Action(ActionEdge::Normal));
        node
    }

    /// Add ActionNode of function call
    fn call_func(&mut self, fname: &str, args: &[NodeIndex], prev_action: NodeIndex,
                 ret_val: Option<NodeIndex>) -> NodeIndex {
        let call_node = self.ast.add_node(SimpleCASTNode::Action(ActionNode::Call(fname.to_string())));
        for (i, arg) in args.iter().enumerate() {
            self.ast.add_edge(call_node, *arg, SimpleCASTEdge::Value(ValueEdge::Arg(i as u8)));
        }
        self.ast.add_edge(prev_action, call_node, SimpleCASTEdge::Action(ActionEdge::Normal));
        if ret_val.is_some() {
            self.ast.add_edge(call_node, ret_val.unwrap(), SimpleCASTEdge::Value(ValueEdge::FuncVal));
        }
        call_node
    }

    fn insert_node(&mut self, prev_action: NodeIndex, next_action: NodeIndex, node: NodeIndex) {
        let e = self.ast.find_edge(prev_action, next_action)
            .map(|x| (x, self.ast.edge_weight(x).map(|a| a.clone())));
        match e {
            Some((idx, Some(SimpleCASTEdge::Action(_)))) => {
                self.ast.remove_edge(idx);
                self.ast.add_edge(prev_action, node, SimpleCASTEdge::Action(ActionEdge::Normal));
                self.ast.add_edge(node, next_action, SimpleCASTEdge::Action(ActionEdge::Normal));
                eprintln!("add edge {:?} to {:?}", prev_action, node);
                eprintln!("add edge {:?} to {:?}", node, next_action);
            },
            _ => {
                radeco_warn!("Invalid nodes {}, {}", prev_action, next_action);
            },
        }
    }

    fn remove_incoming_actions(&mut self, node: NodeIndex) {
        let ns = self.ast.edges_directed(node, Direction::Incoming)
            .into_iter()
            .filter_map(|e| {
                match e.weight() {
                    SimpleCASTEdge::Action(_) => Some(e.id()),
                    _ => None,
                }
            }).collect::<Vec<_>>();
        for e in ns {
            self.ast.remove_edge(e);
        }
    }

    /// Add ActionNode of if statement
    fn conditional(&mut self, condition: NodeIndex, if_then: NodeIndex,
                   if_else: Option<NodeIndex>, prev_action: NodeIndex) -> NodeIndex {
        let node = self.ast.add_node(SimpleCASTNode::Action(ActionNode::If));
        self.remove_incoming_actions(if_then);
        if if_else.is_some() {
            self.remove_incoming_actions(if_else.unwrap());
            self.ast.add_edge(node, if_else.unwrap(), SimpleCASTEdge::Action(ActionEdge::IfElse));
        }
        self.ast.add_edge(node, if_then, SimpleCASTEdge::Action(ActionEdge::IfThen));
        self.ast.add_edge(node, condition, SimpleCASTEdge::Value(ValueEdge::Conditional));
        self.ast.add_edge(prev_action, node, SimpleCASTEdge::Action(ActionEdge::Normal));
        node
    }

    /// Add ActionNode of return statement
    fn add_return(&mut self, ret_val: Option<NodeIndex>, prev_action: NodeIndex) -> NodeIndex {
        let node = self.ast.add_node(SimpleCASTNode::Action(ActionNode::Return));
        if ret_val.is_some() {
            self.ast.add_edge(node, ret_val.unwrap(), SimpleCASTEdge::Value(ValueEdge::RetVal));
        }
        self.ast.add_edge(prev_action, node, SimpleCASTEdge::Action(ActionEdge::Normal));
        node
    }

    fn add_goto(&mut self, dst: NodeIndex, label_str: &str, prev_action: NodeIndex) -> NodeIndex {
        let node = self.ast.add_node(SimpleCASTNode::Action(ActionNode::Goto));
        self.ast.add_edge(node, dst, SimpleCASTEdge::Value(ValueEdge::GotoDst));
        self.ast.add_edge(prev_action, node, SimpleCASTEdge::Action(ActionEdge::Normal));
        self.label_map.insert(dst, label_str.to_string());
        node
    }

    fn insert_goto(&mut self, prev_action: NodeIndex, next_action: NodeIndex,
                   dst: NodeIndex, label_str: &str) -> NodeIndex {
        let node = self.ast.add_node(SimpleCASTNode::Action(ActionNode::Goto));
        let _ = self.ast.add_edge(node, dst, SimpleCASTEdge::Value(ValueEdge::GotoDst));
        self.insert_node(prev_action, next_action, node);
        self.label_map.insert(dst, label_str.to_string());
        node
    }

    fn next_actions(&self, idx: NodeIndex) -> Vec<NodeIndex> {
        self.ast.edges_directed(idx, Direction::Outgoing)
            .into_iter()
            .filter_map(|e| {
                match e.weight() {
                    &SimpleCASTEdge::Action(_) => Some(e.target()),
                    _ => None,
                }
            }).collect()
    }

    /// Returns a pair (IfThen, IfElse)
    fn branch(&self, idx: NodeIndex) -> Option<(NodeIndex, Option<NodeIndex>)> {
        if self.ast.node_weight(idx) != Some(&SimpleCASTNode::Action(ActionNode::If)) {
            return None;
        }
        let ns = self.ast.edges_directed(idx, Direction::Outgoing).into_iter().collect();
        let if_then = neighbors_by_edge(&ns, &SimpleCASTEdge::Action(ActionEdge::IfThen))
            .first().map(|e| e.clone());
        let if_else = neighbors_by_edge(&ns, &SimpleCASTEdge::Action(ActionEdge::IfElse))
            .first().map(|e| e.clone());
        if if_then.is_some() {
            Some((if_then.unwrap(), if_else))
        } else {
            None
        }
    }

    /// Returns value node which represents condition used by If statement
    fn branch_condition(&self, idx: NodeIndex) -> Option<NodeIndex> {
        if self.ast.node_weight(idx) != Some(&SimpleCASTNode::Action(ActionNode::If)) {
            return None;
        }
        let ns = self.ast.edges_directed(idx, Direction::Outgoing).into_iter().collect();
        let expr = {
            let tmp = neighbors_by_edge(&ns, &SimpleCASTEdge::Value(ValueEdge::Conditional));
            if tmp.len() > 1 {
                radeco_warn!("More than one expressions found: If");
            }
            tmp.first().map(|e| e.clone())
        };
        expr
    }

    /// Returns destination of goto statement
    fn goto(&self, idx: NodeIndex) -> Option<NodeIndex> {
        if self.ast.node_weight(idx) != Some(&SimpleCASTNode::Action(ActionNode::Goto))  {
            return None;
        };
        let goto_dsts = self.ast.edges_directed(idx, Direction::Outgoing)
            .into_iter()
            .filter_map(|e| {
                match e.weight() {
                    &SimpleCASTEdge::Value(ValueEdge::GotoDst) => Some(e.target()),
                    _ => None,
                }
            }).collect::<Vec<_>>();
        if goto_dsts.len() > 1 {
            radeco_warn!("More than 1 labels found as Goto destination");
            return None;
        };
        goto_dsts.first().map(|n| n.clone())
    }

    /// Returns a pair (Dst, Src) which represents Dst = Src
    fn assignment(&self, idx: NodeIndex) -> Option<(NodeIndex, NodeIndex)> {
        if self.ast.node_weight(idx) != Some(&SimpleCASTNode::Action(ActionNode::Assignment)) {
            return None;
        }
        let ns = self.ast.edges_directed(idx, Direction::Outgoing).into_iter().collect();
        let src = neighbors_by_edge(&ns, &SimpleCASTEdge::Value(ValueEdge::AssignSrc))
            .first().map(|e| e.clone());
        let dst = neighbors_by_edge(&ns, &SimpleCASTEdge::Value(ValueEdge::AssignDst))
            .first().map(|e| e.clone());
        if src.is_some() && dst.is_some() {
            return Some((dst.unwrap(), src.unwrap()))
        };
        None
    }

    /// Returns arguments of function call
    fn args_call(&self, idx: NodeIndex) -> Option<Vec<NodeIndex>> {
        match self.ast.node_weight(idx) {
            Some(&SimpleCASTNode::Action(ActionNode::Call(_))) => {},
            _ => {return None;},
        };
        let mut args = self.ast.edges_directed(idx, Direction::Outgoing)
            .into_iter()
            .filter_map(|e| {
                match e.weight() {
                    &SimpleCASTEdge::Value(ValueEdge::Arg(o)) => Some((o, e.target())),
                    _ => None,
                }
            }).collect::<Vec<_>>();
        args.sort_by_key(|k| k.0);
        let ret = args.into_iter()
            .map(|(_, b)| b)
            .collect();
        Some(ret)
    }

    /// Returns value node which is assigned by a given function call
    fn func_val(&self, idx: NodeIndex) -> Option<NodeIndex> {
        match self.ast.node_weight(idx) {
            Some(&SimpleCASTNode::Action(ActionNode::Call(_))) => {},
            _ => {return None;},
        };
        let ret = self.ast.edges_directed(idx, Direction::Outgoing)
            .into_iter()
            .filter_map(|e| {
                match e.weight() {
                    &SimpleCASTEdge::Value(ValueEdge::FuncVal) => Some(e.target()),
                    _ => None,
                }
            }).collect::<Vec<_>>();
        if ret.len() > 1 {
            radeco_warn!("More than one variable found for FuncVal");
        }
        ret.first().map(|x| *x)
    }

    /// Returns value node of the return value of a return statement
    fn ret_val(&self, idx: NodeIndex) -> Option<NodeIndex> {
        match self.ast.node_weight(idx) {
            Some(&SimpleCASTNode::Action(ActionNode::Return)) => {},
            _ => {return None;}
        };
        let ret_val = self.ast.edges_directed(idx, Direction::Outgoing)
            .into_iter()
            .filter_map(|e| {
                match e.weight() {
                    &SimpleCASTEdge::Value(ValueEdge::RetVal) => Some(e.target()),
                    _ => None,
                }
            }).collect::<Vec<_>>();
        if ret_val.len() > 1 {
            radeco_warn!("More than one return values found");
        };
        ret_val.into_iter().next()
    }

    /// Returns operands used by a given expression
    fn operands_from_expr(&self, expr: NodeIndex) -> Vec<NodeIndex> {
        let mut operands = self.ast.edges_directed(expr, Direction::Outgoing)
            .into_iter()
            .filter_map(|e| {
                match e.weight() {
                    &SimpleCASTEdge::Value(ValueEdge::Operand(i)) => Some((i, e.target())),
                    _ => None,
                }
            }).collect::<Vec<_>>();
        operands.sort_by_key(|k| k.0);
        operands.into_iter().map(|(_, n)| n).collect::<Vec<_>>()
    }

    /// Entry point of Simple-C-AST to C-AST conversion.
    pub fn to_c_ast(&mut self) -> CAST {
        let mut c_ast = CAST::new(&self.fname);
        for var in self.vars.iter() {
            if let Some(&SimpleCASTNode::Value(ValueNode::Variable(ref var_name))) = self.ast.node_weight(*var) {
                // TODO use given type from ValueNode
                let n = c_ast.declare_vars(c_simple::Ty::new(c_simple::BTy::Int, false, 0), &[var_name.to_string()]);
                // XXX
                self.node_map.insert(*var, n[0]);
            }
        }
        for expr in self.exprs.iter() {
            if let Some(&SimpleCASTNode::Value(ValueNode::Expression(ref op))) = self.ast.node_weight(*expr) {
                let operands = self.operands_from_expr(*expr)
                    .into_iter()
                    .map(|_n| {
                        if let Some(&n) = self.node_map.get(&_n) {
                            n
                        } else {
                            radeco_warn!("NodeIndex {:?} not found", _n);
                            NodeIndex::end()
                        }
                    }).collect::<Vec<_>>();
                let n = c_ast.expr(op.clone(), &operands);
                self.node_map.insert(*expr, n);
            }
        }
        let entry = self.entry;
        self.to_c_ast_body(&mut c_ast, entry);
        c_ast
    }

    fn to_c_ast_body(&mut self, c_ast: &mut CAST, current_node: NodeIndex) {
        if self.visited.contains(&current_node) {
            return;
        };
        self.visited.insert(current_node);
        eprintln!("current: {:?}", current_node);
        if let Some(ref l) = self.label_map.get(&current_node) {
            eprintln!("Label at {:?}", current_node);
            let node = c_ast.label(l);
            self.label_node_map.insert(current_node, node);
        };
        let idx = self.ast.node_weight(current_node).map(|x| x.clone());
        match idx {
            Some(SimpleCASTNode::Action(ActionNode::Assignment)) => {
                let tmp = self.assignment(current_node)
                    .and_then(|(d, s)| {
                        match (self.node_map.get(&d), self.node_map.get(&s)) {
                            (Some(&x), Some(&y)) => Some((x.clone(), y.clone())),
                            _ => None
                        }
                    });
                if let Some((dst, src)) = tmp {
                    let node = c_ast.expr(c_simple::Expr::Assign, &[dst, src]);
                    self.node_map.insert(current_node, node);
                } else {
                    radeco_err!("Something wrong");
                }
            },
            Some(SimpleCASTNode::Action(ActionNode::Call(ref name))) => {
                let args = self.args_call(current_node)
                    .unwrap_or(Vec::new())
                    .into_iter()
                    .map(|arg| {
                        let ret = self.node_map.get(&arg).map(|a| *a);
                        if ret.is_none() {
                            radeco_warn!("Error args_call");
                        }
                        ret
                    }).collect();
                let ret_node_opt = self.func_val(current_node)
                    .and_then(|x| self.node_map.get(&x).map(|a| *a));
                let node = c_ast.call_func(name, args);
                if let Some(ret_node) = ret_node_opt {
                    c_ast.expr(c_simple::Expr::Assign, &[ret_node, node]);
                }
                self.node_map.insert(current_node, node);
            },
            Some(SimpleCASTNode::Action(ActionNode::Return)) => {
                let opt = self.ret_val(current_node)
                    .and_then(|n| self.node_map.get(&n))
                    .map(|n| *n);
                let node = c_ast.ret(opt);
                self.node_map.insert(current_node, node);
            },
            Some(SimpleCASTNode::Action(ActionNode::If)) => {
                let cond = self.branch_condition(current_node);
                let branches = self.branch(current_node).map(|x| x.clone());
                if let (Some((if_then, if_else)), Some(cond)) = (branches, cond) {
                    self.to_c_ast_body(c_ast, if_then);
                    if if_else.is_some() {
                        self.to_c_ast_body(c_ast, if_else.unwrap());
                    }
                    // TODO avoid unwrap
                    let c = *self.node_map.get(&cond).unwrap();
                    let t = *self.node_map.get(&if_then).unwrap();
                    let e = if_else.and_then(|x| self.node_map.get(&x)).map(|x| *x);
                    let node = c_ast.new_conditional(c, t, e);
                    self.node_map.insert(current_node, node);
                }
            },
            Some(SimpleCASTNode::Action(ActionNode::Goto)) => {
                let reserved_edge = if self.goto(current_node)
                    .and_then(|d| self.label_node_map.get(&d)).is_some() {
                        None
                    } else {
                        let ret = c_ast.reserve_edge();
                        for n in self.next_actions(current_node) {
                            self.to_c_ast_body(c_ast, n);
                        }
                        Some(ret)
                    };
                let dst_opt = self.goto(current_node)
                    .and_then(|d| self.label_node_map.get(&d))
                    .map(|d| d.clone());
                if let Some(dst) = dst_opt {
                    // TODO avoid unwrap
                    let node = c_ast.goto(dst, reserved_edge.is_none()).unwrap();
                    if reserved_edge.is_some() {
                        c_ast.replace_node(reserved_edge.unwrap(), node);
                    }
                    self.node_map.insert(current_node, node);
                } else {
                    radeco_warn!("Error Goto");
                }
            },
            Some(SimpleCASTNode::Entry) => {},
            _ => unreachable!(),
        };
        for n in self.next_actions(current_node) {
            self.to_c_ast_body(c_ast, n);
        }
        c_ast
    }

}
<|endoftext|>


<commit_before>use std::path::Path;
use std::fs;
use std::io::Write;
use error::*;
use config::Config;

const COBALT_YML: &'static [u8] = b"name: cobalt blog
source: \".\"
dest: \"./_site\"
";

const DEFAULT_LAYOUT: &'static [u8] = b"<!DOCTYPE html>

        <meta charset=\"utf-8\">
        {% if is_post %}
          <title>{{ title }}</title>
        {% else %}
          <title>Cobalt.rs Blog</title>
        {% endif %}

      {% if is_post %}
        {% include '_layouts/post.liquid' %}
      {% else %}
        {{ content }}
      {% endif %}

";

const POST_LAYOUT: &'static [u8] = b"

{{ title }}

    {{content}}

";

const POST_MD: &'static [u8] = b"extends: default.liquid

title: First Post
date: 14 January 2016 21:00:30 -0500
---

# This is our first Post!

Welcome to the first post ever on cobalt.rs!
";

const INDEX_LIQUID: &'static [u8] = b"extends: default.liquid
---

Blog!

    {% for post in posts %}

{{post.title}}

{{ post.title }}

    {% endfor %}

";

pub fn create_new_project<P: AsRef<Path>>(dest: P) -> Result<()> {
    create_new_project_for_path(dest.as_ref())
}

pub fn create_new_project_for_path(dest: &Path) -> Result<()> {
    fs::create_dir_all(dest)?;

    create_file(&dest.join(".cobalt.yml"), COBALT_YML)?;
    create_file(&dest.join("index.liquid"), INDEX_LIQUID)?;

    fs::create_dir_all(&dest.join("_layouts"))?;
    create_file(&dest.join("_layouts/default.liquid"), DEFAULT_LAYOUT)?;
    create_file(&dest.join("_layouts/post.liquid"), POST_LAYOUT)?;

    fs::create_dir_all(&dest.join("posts"))?;
    create_file(&dest.join("posts/post-1.md"), POST_MD)?;

    Ok(())
}

pub fn create_new_document(doc_type: &str, name: &str, config: &Config) -> Result<()> {
    let path = Path::new(&config.source);
    let full_path = &path.join(&config.posts.dir).join(name);

    match doc_type {
        "page" => create_file(name, INDEX_LIQUID)?,
        "post" => create_file(full_path, POST_MD)?,
        _ => bail!("Unsupported document type {}", doc_type),
    }

    Ok(())
}

fn create_file<P: AsRef<Path>>(path: P, content: &[u8]) -> Result<()> {
    create_file_for_path(path.as_ref(), content)
}

fn create_file_for_path(path: &Path, content: &[u8]) -> Result<()> {
    trace!("Creating file {:?}", path);

    let mut file = fs::OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(path)
        .chain_err(|| format!("Failed to create file {:?}", path))?;

    file.write_all(content)?;

    Ok(())
}
<commit_msg>fix(new): Auto-created posts start as drafts<commit_after>use std::path::Path;
use std::fs;
use std::io::Write;
use error::*;
use config::Config;

const COBALT_YML: &'static [u8] = b"name: cobalt blog
source: \".\"
dest: \"./_site\"
";

const DEFAULT_LAYOUT: &'static [u8] = b"<!DOCTYPE html>

        <meta charset=\"utf-8\">
        {% if is_post %}
          <title>{{ title }}</title>
        {% else %}
          <title>Cobalt.rs Blog</title>
        {% endif %}

      {% if is_post %}
        {% include '_layouts/post.liquid' %}
      {% else %}
        {{ content }}
      {% endif %}

";

const POST_LAYOUT: &'static [u8] = b"

{{ title }}

    {{content}}

";

const POST_MD: &'static [u8] = b"extends: default.liquid

title: First Post
draft: true
---

# This is our first Post!

Welcome to the first post ever on cobalt.rs!
";

const INDEX_LIQUID: &'static [u8] = b"extends: default.liquid
---

Blog!

    {% for post in posts %}

{{post.title}}

{{ post.title }}

    {% endfor %}

";

pub fn create_new_project<P: AsRef<Path>>(dest: P) -> Result<()> {
    create_new_project_for_path(dest.as_ref())
}

pub fn create_new_project_for_path(dest: &Path) -> Result<()> {
    fs::create_dir_all(dest)?;

    create_file(&dest.join(".cobalt.yml"), COBALT_YML)?;
    create_file(&dest.join("index.liquid"), INDEX_LIQUID)?;

    fs::create_dir_all(&dest.join("_layouts"))?;
    create_file(&dest.join("_layouts/default.liquid"), DEFAULT_LAYOUT)?;
    create_file(&dest.join("_layouts/post.liquid"), POST_LAYOUT)?;

    fs::create_dir_all(&dest.join("posts"))?;
    create_file(&dest.join("posts/post-1.md"), POST_MD)?;

    Ok(())
}

pub fn create_new_document(doc_type: &str, name: &str, config: &Config) -> Result<()> {
    let path = Path::new(&config.source);
    let full_path = &path.join(&config.posts.dir).join(name);

    match doc_type {
        "page" => create_file(name, INDEX_LIQUID)?,
        "post" => create_file(full_path, POST_MD)?,
        _ => bail!("Unsupported document type {}", doc_type),
    }

    Ok(())
}

fn create_file<P: AsRef<Path>>(path: P, content: &[u8]) -> Result<()> {
    create_file_for_path(path.as_ref(), content)
}

fn create_file_for_path(path: &Path, content: &[u8]) -> Result<()> {
    trace!("Creating file {:?}", path);

    let mut file = fs::OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(path)
        .chain_err(|| format!("Failed to create file {:?}", path))?;

    file.write_all(content)?;

    Ok(())
}
<|endoftext|>