<commit_before>//! Provides a material for modelling metal surfaces of varying roughness
//! using the Torrance Sparrow BRDF and a Blinn microfacet distribution
//! TODO: Add Ashikman-Shirley (spelling?) anisotropic microfacet model

use std::vec::Vec;

use film::Colorf;
use geometry::Intersection;
use bxdf::{BxDF, BSDF, TorranceSparrow};
use bxdf::microfacet::{MicrofacetDistribution, Blinn};
use bxdf::fresnel::{Fresnel, Conductor};
use material::Material;

/// The Metal material describes metals of varying roughness
pub struct Metal {
    bxdfs: Vec<Box<BxDF + Send + Sync>>,
}

impl Metal {
    /// Create a new metal material specifying the reflectance properties of the metal
    pub fn new(refr_index: &Colorf, absorption_coef: &Colorf, roughness: f32) -> Metal {
        let fresnel = Box::new(Conductor::new(refr_index, absorption_coef)) as Box<Fresnel + Send + Sync>;
        let microfacet = Box::new(Blinn::new(1.0 / roughness)) as Box<MicrofacetDistribution + Send + Sync>;
        Metal { bxdfs: vec![Box::new(TorranceSparrow::new(&Colorf::broadcast(1.0), fresnel, microfacet))
                            as Box<BxDF + Send + Sync>] }
    }
}

impl Material for Metal {
    fn bsdf<'a, 'b>(&'a self, hit: &Intersection<'a, 'b>) -> BSDF<'a> {
        BSDF::new(&self.bxdfs, 1.0, &hit.dg)
    }
}

<commit_msg>Match specular_metal naming conventions in Metal<commit_after>//! Provides a material for modelling metal surfaces of varying roughness
//! using the Torrance Sparrow BRDF and a Blinn microfacet distribution
//! TODO: Add Ashikman-Shirley (spelling?) anisotropic microfacet model

use std::vec::Vec;

use film::Colorf;
use geometry::Intersection;
use bxdf::{BxDF, BSDF, TorranceSparrow};
use bxdf::microfacet::{MicrofacetDistribution, Blinn};
use bxdf::fresnel::{Fresnel, Conductor};
use material::Material;

/// The Metal material describes metals of varying roughness
pub struct Metal {
    bxdfs: Vec<Box<BxDF + Send + Sync>>,
}

impl Metal {
    /// Create a new metal material specifying the reflectance properties of the metal
    pub fn new(eta: &Colorf, k: &Colorf, roughness: f32) -> Metal {
        let fresnel = Box::new(Conductor::new(eta, k)) as Box<Fresnel + Send + Sync>;
        let microfacet = Box::new(Blinn::new(1.0 / roughness)) as Box<MicrofacetDistribution + Send + Sync>;
        Metal { bxdfs: vec![Box::new(TorranceSparrow::new(&Colorf::broadcast(1.0), fresnel, microfacet))
                            as Box<BxDF + Send + Sync>] }
    }
}

impl Material for Metal {
    fn bsdf<'a, 'b>(&'a self, hit: &Intersection<'a, 'b>) -> BSDF<'a> {
        BSDF::new(&self.bxdfs, 1.0, &hit.dg)
    }
}

<|endoftext|>


<commit_before>use postgres;
use uuid::Uuid;
use std::fmt;
use chrono::{NaiveDateTime, Utc, DateTime};

use apple_music;
use youtube;
use youtube::HasThumbnail;
use soundcloud;
use spotify;
use error::Error;
use super::{conn, Model};
use model::provider::Provider;
use model::state::State;
use model::enclosure::Enclosure;
use model::track::Track;

static PROPS: [&'static str; 14]  = ["id",
                                     "provider",
                                     "identifier",
                                     "owner_id",
                                     "owner_name",
                                     "url",
                                     "title",
                                     "description",
                                     "thumbnail_url",
                                     "artwork_url",
                                     "published_at",
                                     "created_at",
                                     "updated_at",
                                     "state"];

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Playlist {
    pub id:            Uuid,
    pub provider:      Provider,
    pub identifier:    String,
    pub owner_id:      Option<String>,
    pub owner_name:    Option<String>,
    pub url:           String,
    pub title:         String,
    pub description:   Option<String>,
    pub thumbnail_url: Option<String>,
    pub artwork_url:   Option<String>,
    pub published_at:  NaiveDateTime,
    pub created_at:    NaiveDateTime,
    pub updated_at:    NaiveDateTime,
    pub state:         State,
    pub tracks:        Vec<Track>,
}

impl PartialEq for Playlist {
    fn eq(&self, p: &Playlist) -> bool {
        return self.identifier == p.identifier && self.provider == p.provider
    }
}

impl fmt::Display for Playlist {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}:{}", self.provider, self.identifier)
    }
}

impl<'a> Model<'a> for Playlist {
    fn table_name() -> String { "playlists".to_string() }
    fn props_str(prefix: &str) -> String {
        PROPS
            .iter()
            .map(|&p| format!("{}{}", prefix, p))
            .collect::<Vec<String>>().join(",")
    }
    fn rows_to_items(rows: postgres::rows::Rows) -> Vec<Playlist> {
        let mut playlists = Vec::new();
        for row in rows.iter() {
            let playlist = Playlist {
                id:            row.get(0),
                provider:      Provider::new(row.get(1)),
                identifier:    row.get(2),
                owner_id:      row.get(3),
                owner_name:    row.get(4),
                url:           row.get(5),
                title:         row.get(6),
                description:   row.get(7),
                thumbnail_url: row.get(8),
                artwork_url:   row.get(9),
                published_at:  row.get(10),
                created_at:    row.get(11),
                updated_at:    row.get(12),
                state:         State::new(row.get(13)),
                tracks:        vec![], // TODO
            };
            playlists.push(playlist)
        }
        playlists
    }

    fn create(&self) -> Result<Playlist, Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("INSERT INTO playlists (provider, identifier, url, title)
                                 VALUES ($1, $2, $3, $4) RETURNING id"));
        let rows = try!(stmt.query(&[&self.provider.to_string(), &self.identifier, &self.url, &self.title]));
        let mut playlist = self.clone();
        for row in rows.iter() {
            playlist.id = row.get(0);
        }
        Ok(playlist)
    }

    fn save(&mut self) -> Result<(), Error> {
        self.updated_at = Utc::now().naive_utc();
        let conn = try!(conn());
        let stmt = try!(conn.prepare("UPDATE playlists SET
                                      provider      = $2,
                                      identifier    = $3,
                                      owner_id      = $4,
                                      owner_name    = $5,
                                      url           = $6,
                                      title         = $7,
                                      description   = $8,
                                      thumbnail_url = $9,
                                      artwork_url   = $10,
                                      published_at  = $11,
                                      created_at    = $12,
                                      updated_at    = $13,
                                      state         = $14
                                      WHERE id = $1"));
        let result = stmt.query(&[&self.id,
                                  &self.provider.to_string(),
                                  &self.identifier,
                                  &self.owner_id,
                                  &self.owner_name,
                                  &self.url,
                                  &self.title,
                                  &self.description,
                                  &self.thumbnail_url,
                                  &self.artwork_url,
                                  &self.published_at,
                                  &self.created_at,
                                  &self.updated_at,
                                  &self.state.to_string(),
        ]);
        match result {
            Ok(_)  => Ok(()),
            Err(_) => Err(Error::Unexpected),
        }
    }
}

impl<'a> Enclosure<'a> for Playlist {
    fn new(provider: Provider, identifier: String) -> Playlist {
        Playlist {
            id:            Uuid::new_v4(),
            provider:      provider,
            identifier:    identifier,
            owner_id:      None,
            owner_name:    None,
            url:           "".to_string(),
            title:         "".to_string(),
            description:   None,
            thumbnail_url: None,
            artwork_url:   None,
            published_at:  Utc::now().naive_utc(),
            created_at:    Utc::now().naive_utc(),
            updated_at:    Utc::now().naive_utc(),
            state:         State::Alive,
            tracks:        vec![],
        }
    }
    fn set_url(&mut self, url: String) -> &mut Playlist {
        self.url = url;
        self
    }
    fn set_owner_id(&mut self, owner_id: Option<String>) -> &mut Playlist {
        self.owner_id = owner_id;
        self
    }
    fn fetch_props(&mut self) -> Result<(), Error> {
        match self.provider {
            Provider::YouTube => {
                let items = youtube::fetch_playlist_items(&self.identifier)
                    .map(|res| res.items)
                    .unwrap_or(vec![]);
                if let Ok(res) = youtube::fetch_playlist(&self.identifier) {
                    if let Some(playlist) = res.items.iter().nth(0) {
                        self.update_with_yt_playlist(&playlist, &items);
                    }
                }
                self.disable();
            },
            Provider::SoundCloud => {
                match soundcloud::fetch_playlist(&self.identifier) {
                    Ok(playlist) => self.update_with_sc_playlist(&playlist),
                    Err(_)       => self.disable()
                };
            },
            Provider::AppleMusic => {
                let country = apple_music::country(&self.url);
                match apple_music::fetch_playlist(&self.identifier, &country) {
                    Ok(playlist) => self.update_with_am_playlist(&playlist),
                    Err(_)       => self.disable(),
                };
            },
            Provider::Spotify => {
                if let Some(owner_id) = self.clone().owner_id {
                    match spotify::fetch_playlist(&owner_id, &self.identifier) {
                        Ok(playlist) => {
                            self.update_with_sp_playlist(&playlist);
                        },
                        Err(_)       => {
                            self.disable();
                        },
                    }
                }
            },
            _ => (),
        };
        match self.state {
            State::Alive => Ok(()),
            State::Dead  => Err(Error::NotFound),
        }
    }
    fn find_by_entry_id(entry_id: Uuid) -> Vec<Playlist> {
        let conn = conn().unwrap();
        let stmt = conn.prepare(
            &format!("SELECT {} FROM playlists p LEFT JOIN playlist_entries pe
                        ON p.id = pe.playlist_id
                        WHERE pe.entry_id = $1
                        ORDER BY p.published_at DESC",
                     Playlist::props_str("p."))).unwrap();
        let rows = stmt.query(&[&entry_id]).unwrap();
        Playlist::rows_to_items(rows)
    }
}

impl Playlist {
    pub fn add_track(&mut self, track: &Track) -> Result<(), Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("INSERT INTO playlist_tracks (track_id, playlist_id)
                                      VALUES ($1, $2)"));
        try!(stmt.query(&[&track.id, &self.id]));
        Ok(())
    }

    pub fn from_yt_playlist(playlist: &youtube::Playlist, items: &Vec<youtube::PlaylistItem>) -> Playlist {
        Playlist::new(Provider::YouTube, (*playlist).id.to_string())
            .update_with_yt_playlist(playlist, items)
            .clone()
    }

    pub fn from_sp_playlist(playlist: &spotify::Playlist) -> Playlist {
        Playlist::new(Provider::Spotify, (*playlist).id.to_string())
            .update_with_sp_playlist(playlist)
            .clone()
    }

    pub fn from_sc_playlist(playlist: &soundcloud::Playlist) -> Playlist {
        Playlist::new(Provider::SoundCloud, (*playlist).id.to_string())
            .update_with_sc_playlist(playlist)
            .clone()
    }

    pub fn from_am_playlist(playlist: &apple_music::Playlist) -> Playlist {
        Playlist::new(Provider::AppleMusic, (*playlist).id.to_string())
            .update_with_am_playlist(playlist)
            .clone()
    }

    fn add_tracks(&mut self, tracks: Vec<Track>) {
        self.tracks = tracks.iter().map(|t| {
            let mut t = t.clone();
            if let Ok(new_track) = Track::find_or_create(t.provider,
                                                         t.identifier.to_string()) {
                t.id      = new_track.id;
                let _     = self.add_track(&t);
            };
            t
        }).collect::<Vec<_>>();
    }

    pub fn update_with_yt_playlist(&mut self, playlist: &youtube::Playlist, items: &Vec<youtube::PlaylistItem>) -> &mut Playlist {
        self.provider      = Provider::YouTube;
        self.identifier    = playlist.id.to_string();
        self.owner_id      = Some(playlist.snippet.channelId.to_string());
        self.owner_name    = Some(playlist.snippet.channelTitle.to_string());
        self.url           = format!("https://www.youtube.com/playlist?list={}", playlist.id);
        self.title         = playlist.snippet.title.to_string();
        self.description   = Some(playlist.snippet.description.to_string());
        self.thumbnail_url = playlist.snippet.get_thumbnail_url();
        self.artwork_url   = playlist.snippet.get_artwork_url();
        self.state         = State::Alive;
        match DateTime::parse_from_rfc3339(&playlist.snippet.publishedAt) {
            Ok(published_at) => self.published_at = published_at.naive_utc(),
            Err(_)           => (),
        }
        let tracks = items.iter()
            .map(|ref i| Track::from_yt_playlist_item(i))
            .collect::<Vec<_>>();
        self.add_tracks(tracks);
        self
    }

    pub fn update_with_sp_playlist(&mut self, playlist: &spotify::Playlist) -> &mut Playlist {
        self.provider       = Provider::Spotify;
        self.identifier     = playlist.id.to_string();
        self.owner_id       = Some(playlist.owner.id.to_string());
        self.owner_name     = playlist.owner.display_name.clone();
        self.url            = playlist.uri.clone();
        self.title          = playlist.name.clone();
        self.description    = playlist.description.clone();
        self.state          = State::Alive;
        self.published_at   = Utc::now().naive_utc();
        if playlist.images.len() > 0 {
            self.artwork_url   = Some(playlist.images[0].url.clone());
            self.thumbnail_url = Some(playlist.images[0].url.clone());
        }
        if playlist.images.len() > 1 {
            self.thumbnail_url = Some(playlist.images[1].url.clone());
        }
        let tracks = playlist.tracks.items.iter()
            .map(|ref i| Track::from_sp_track(&i.track))
            .collect::<Vec<_>>();
        self.add_tracks(tracks);
        self
    }

    pub fn update_with_sc_playlist(&mut self, playlist: &soundcloud::Playlist) -> &mut Playlist {
        self.provider      = Provider::SoundCloud;
        self.identifier    = playlist.id.to_string();
        self.owner_id      = Some(playlist.user.id.to_string());
        self.owner_name    = Some(playlist.user.username.clone());
        self.url           = playlist.permalink_url.to_string();
        self.title         = playlist.title.to_string();
        self.description   = None;
        self.thumbnail_url = playlist.artwork_url.clone();
        self.artwork_url   = playlist.artwork_url.clone();
        self.state         = State::Alive;
        match DateTime::parse_from_str(&playlist.created_at, "%Y/%m/%d %H:%M:%S %z") {
            Ok(published_at) => self.published_at = published_at.naive_utc(),
            Err(_)           => (),
        };
        let tracks = playlist.tracks.iter()
            .map(|ref t| Track::from_sc_track(t))
            .collect::<Vec<_>>();
        self.add_tracks(tracks);
        self
    }

    pub fn update_with_am_playlist(&mut self, playlist: &apple_music::Playlist) -> &mut Playlist {
        self.provider      = Provider::AppleMusic;
        self.identifier    = playlist.id.to_string();
        self.owner_id      = Some(playlist.curator.to_string());
        self.owner_name    = Some(playlist.curator.to_string());
        self.url           = playlist.music_url.to_string();
        self.title         = playlist.title.to_string();
        self.description   = Some(playlist.description.to_string());
        self.thumbnail_url = Some(playlist.artwork_url.to_string());
        self.artwork_url   = Some(playlist.artwork_url.to_string());
        self.state         = State::Alive;
        self
    }

    pub fn disable(&mut self) -> &mut Playlist {
        self.state = State::Dead;
        self
    }

    pub fn delete(&self) -> Result<(), Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("DELETE FROM playlists WHERE id=$1"));
        let result = stmt.query(&[&self.id]);
        match result {
            Ok(_)  => Ok(()),
            Err(_) => Err(Error::Unexpected)
        }
    }
}

#[cfg(test)]
mod test {
    use model::enclosure::Enclosure;
    use model::Model;
    use super::Playlist;
    use Provider;
    #[test]
    fn test_new() {
        let playlist = Playlist::new(Provider::YouTube,
                                     "PLy8LZ8FM-o0ViuGAF68RAaXkQ8V-3dbTX".to_string());
        assert_eq!(playlist.provider, Provider::YouTube);
        assert_eq!(&playlist.identifier, "PLy8LZ8FM-o0ViuGAF68RAaXkQ8V-3dbTX")
    }
    #[test]
    fn test_find_of_create() {
        let identifier = "PLy8LZ8FM-o0ViuGAF68RAaXkQ8V-3dbTX".to_string();
        let result     = Playlist::find_or_create(Provider::YouTube, identifier);
        assert!(result.is_ok());
    }
    #[test]
    fn test_delete() {
        let identifier = "test_delete".to_string();
        let playlist   = Playlist::find_or_create(Provider::YouTube, identifier).unwrap();
        let result     = playlist.delete();
        assert!(result.is_ok());
    }
    #[test]
    fn test_save() {
        let id = "test_save";
        let mut playlist = Playlist::find_or_create(Provider::YouTube, id.to_string()).unwrap();
        playlist.title = "title".to_string();
        let result = playlist.save();
        assert!(result.is_ok());
        let playlist = Playlist::find_or_create(Provider::YouTube, id.to_string()).unwrap();
        assert_eq!(&playlist.title, "title");
    }
}
<commit_msg>Update Playlist::update_with_am_playlist<commit_after>use postgres;
use uuid::Uuid;
use std::fmt;
use chrono::{NaiveDateTime, Utc, DateTime};

use apple_music;
use youtube;
use youtube::HasThumbnail;
use soundcloud;
use spotify;
use error::Error;
use super::{conn, Model};
use model::provider::Provider;
use model::state::State;
use model::enclosure::Enclosure;
use model::track::Track;

static PROPS: [&'static str; 14]  = ["id",
                                     "provider",
                                     "identifier",
                                     "owner_id",
                                     "owner_name",
                                     "url",
                                     "title",
                                     "description",
                                     "thumbnail_url",
                                     "artwork_url",
                                     "published_at",
                                     "created_at",
                                     "updated_at",
                                     "state"];

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Playlist {
    pub id:            Uuid,
    pub provider:      Provider,
    pub identifier:    String,
    pub owner_id:      Option<String>,
    pub owner_name:    Option<String>,
    pub url:           String,
    pub title:         String,
    pub description:   Option<String>,
    pub thumbnail_url: Option<String>,
    pub artwork_url:   Option<String>,
    pub published_at:  NaiveDateTime,
    pub created_at:    NaiveDateTime,
    pub updated_at:    NaiveDateTime,
    pub state:         State,
    pub tracks:        Vec<Track>,
}

impl PartialEq for Playlist {
    fn eq(&self, p: &Playlist) -> bool {
        return self.identifier == p.identifier && self.provider == p.provider
    }
}

impl fmt::Display for Playlist {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}:{}", self.provider, self.identifier)
    }
}

impl<'a> Model<'a> for Playlist {
    fn table_name() -> String { "playlists".to_string() }
    fn props_str(prefix: &str) -> String {
        PROPS
            .iter()
            .map(|&p| format!("{}{}", prefix, p))
            .collect::<Vec<String>>().join(",")
    }
    fn rows_to_items(rows: postgres::rows::Rows) -> Vec<Playlist> {
        let mut playlists = Vec::new();
        for row in rows.iter() {
            let playlist = Playlist {
                id:            row.get(0),
                provider:      Provider::new(row.get(1)),
                identifier:    row.get(2),
                owner_id:      row.get(3),
                owner_name:    row.get(4),
                url:           row.get(5),
                title:         row.get(6),
                description:   row.get(7),
                thumbnail_url: row.get(8),
                artwork_url:   row.get(9),
                published_at:  row.get(10),
                created_at:    row.get(11),
                updated_at:    row.get(12),
                state:         State::new(row.get(13)),
                tracks:        vec![], // TODO
            };
            playlists.push(playlist)
        }
        playlists
    }

    fn create(&self) -> Result<Playlist, Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("INSERT INTO playlists (provider, identifier, url, title)
                                 VALUES ($1, $2, $3, $4) RETURNING id"));
        let rows = try!(stmt.query(&[&self.provider.to_string(), &self.identifier, &self.url, &self.title]));
        let mut playlist = self.clone();
        for row in rows.iter() {
            playlist.id = row.get(0);
        }
        Ok(playlist)
    }

    fn save(&mut self) -> Result<(), Error> {
        self.updated_at = Utc::now().naive_utc();
        let conn = try!(conn());
        let stmt = try!(conn.prepare("UPDATE playlists SET
                                      provider      = $2,
                                      identifier    = $3,
                                      owner_id      = $4,
                                      owner_name    = $5,
                                      url           = $6,
                                      title         = $7,
                                      description   = $8,
                                      thumbnail_url = $9,
                                      artwork_url   = $10,
                                      published_at  = $11,
                                      created_at    = $12,
                                      updated_at    = $13,
                                      state         = $14
                                      WHERE id = $1"));
        let result = stmt.query(&[&self.id,
                                  &self.provider.to_string(),
                                  &self.identifier,
                                  &self.owner_id,
                                  &self.owner_name,
                                  &self.url,
                                  &self.title,
                                  &self.description,
                                  &self.thumbnail_url,
                                  &self.artwork_url,
                                  &self.published_at,
                                  &self.created_at,
                                  &self.updated_at,
                                  &self.state.to_string(),
        ]);
        match result {
            Ok(_)  => Ok(()),
            Err(_) => Err(Error::Unexpected),
        }
    }
}

impl<'a> Enclosure<'a> for Playlist {
    fn new(provider: Provider, identifier: String) -> Playlist {
        Playlist {
            id:            Uuid::new_v4(),
            provider:      provider,
            identifier:    identifier,
            owner_id:      None,
            owner_name:    None,
            url:           "".to_string(),
            title:         "".to_string(),
            description:   None,
            thumbnail_url: None,
            artwork_url:   None,
            published_at:  Utc::now().naive_utc(),
            created_at:    Utc::now().naive_utc(),
            updated_at:    Utc::now().naive_utc(),
            state:         State::Alive,
            tracks:        vec![],
        }
    }
    fn set_url(&mut self, url: String) -> &mut Playlist {
        self.url = url;
        self
    }
    fn set_owner_id(&mut self, owner_id: Option<String>) -> &mut Playlist {
        self.owner_id = owner_id;
        self
    }
    fn fetch_props(&mut self) -> Result<(), Error> {
        match self.provider {
            Provider::YouTube => {
                let items = youtube::fetch_playlist_items(&self.identifier)
                    .map(|res| res.items)
                    .unwrap_or(vec![]);
                if let Ok(res) = youtube::fetch_playlist(&self.identifier) {
                    if let Some(playlist) = res.items.iter().nth(0) {
                        self.update_with_yt_playlist(&playlist, &items);
                    }
                }
                self.disable();
            },
            Provider::SoundCloud => {
                match soundcloud::fetch_playlist(&self.identifier) {
                    Ok(playlist) => self.update_with_sc_playlist(&playlist),
                    Err(_)       => self.disable()
                };
            },
            Provider::AppleMusic => {
                let country = apple_music::country(&self.url);
                match apple_music::fetch_playlist(&self.identifier, &country) {
                    Ok(playlist) => self.update_with_am_playlist(&playlist),
                    Err(_)       => self.disable(),
                };
            },
            Provider::Spotify => {
                if let Some(owner_id) = self.clone().owner_id {
                    match spotify::fetch_playlist(&owner_id, &self.identifier) {
                        Ok(playlist) => {
                            self.update_with_sp_playlist(&playlist);
                        },
                        Err(_)       => {
                            self.disable();
                        },
                    }
                }
            },
            _ => (),
        };
        match self.state {
            State::Alive => Ok(()),
            State::Dead  => Err(Error::NotFound),
        }
    }
    fn find_by_entry_id(entry_id: Uuid) -> Vec<Playlist> {
        let conn = conn().unwrap();
        let stmt = conn.prepare(
            &format!("SELECT {} FROM playlists p LEFT JOIN playlist_entries pe
                        ON p.id = pe.playlist_id
                        WHERE pe.entry_id = $1
                        ORDER BY p.published_at DESC",
                     Playlist::props_str("p."))).unwrap();
        let rows = stmt.query(&[&entry_id]).unwrap();
        Playlist::rows_to_items(rows)
    }
}

impl Playlist {
    pub fn add_track(&mut self, track: &Track) -> Result<(), Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("INSERT INTO playlist_tracks (track_id, playlist_id)
                                      VALUES ($1, $2)"));
        try!(stmt.query(&[&track.id, &self.id]));
        Ok(())
    }

    pub fn from_yt_playlist(playlist: &youtube::Playlist, items: &Vec<youtube::PlaylistItem>) -> Playlist {
        Playlist::new(Provider::YouTube, (*playlist).id.to_string())
            .update_with_yt_playlist(playlist, items)
            .clone()
    }

    pub fn from_sp_playlist(playlist: &spotify::Playlist) -> Playlist {
        Playlist::new(Provider::Spotify, (*playlist).id.to_string())
            .update_with_sp_playlist(playlist)
            .clone()
    }

    pub fn from_sc_playlist(playlist: &soundcloud::Playlist) -> Playlist {
        Playlist::new(Provider::SoundCloud, (*playlist).id.to_string())
            .update_with_sc_playlist(playlist)
            .clone()
    }

    pub fn from_am_playlist(playlist: &apple_music::Playlist) -> Playlist {
        Playlist::new(Provider::AppleMusic, (*playlist).id.to_string())
            .update_with_am_playlist(playlist)
            .clone()
    }

    fn add_tracks(&mut self, tracks: Vec<Track>) {
        self.tracks = tracks.iter().map(|t| {
            let mut t = t.clone();
            if let Ok(new_track) = Track::find_or_create(t.provider,
                                                         t.identifier.to_string()) {
                t.id      = new_track.id;
                let _     = self.add_track(&t);
            };
            t
        }).collect::<Vec<_>>();
    }

    pub fn update_with_yt_playlist(&mut self, playlist: &youtube::Playlist, items: &Vec<youtube::PlaylistItem>) -> &mut Playlist {
        self.provider      = Provider::YouTube;
        self.identifier    = playlist.id.to_string();
        self.owner_id      = Some(playlist.snippet.channelId.to_string());
        self.owner_name    = Some(playlist.snippet.channelTitle.to_string());
        self.url           = format!("https://www.youtube.com/playlist?list={}", playlist.id);
        self.title         = playlist.snippet.title.to_string();
        self.description   = Some(playlist.snippet.description.to_string());
        self.thumbnail_url = playlist.snippet.get_thumbnail_url();
        self.artwork_url   = playlist.snippet.get_artwork_url();
        self.state         = State::Alive;
        match DateTime::parse_from_rfc3339(&playlist.snippet.publishedAt) {
            Ok(published_at) => self.published_at = published_at.naive_utc(),
            Err(_)           => (),
        }
        let tracks = items.iter()
            .map(|ref i| Track::from_yt_playlist_item(i))
            .collect::<Vec<_>>();
        self.add_tracks(tracks);
        self
    }

    pub fn update_with_sp_playlist(&mut self, playlist: &spotify::Playlist) -> &mut Playlist {
        self.provider       = Provider::Spotify;
        self.identifier     = playlist.id.to_string();
        self.owner_id       = Some(playlist.owner.id.to_string());
        self.owner_name     = playlist.owner.display_name.clone();
        self.url            = playlist.uri.clone();
        self.title          = playlist.name.clone();
        self.description    = playlist.description.clone();
        self.state          = State::Alive;
        self.published_at   = Utc::now().naive_utc();
        if playlist.images.len() > 0 {
            self.artwork_url   = Some(playlist.images[0].url.clone());
            self.thumbnail_url = Some(playlist.images[0].url.clone());
        }
        if playlist.images.len() > 1 {
            self.thumbnail_url = Some(playlist.images[1].url.clone());
        }
        let tracks = playlist.tracks.items.iter()
            .map(|ref i| Track::from_sp_track(&i.track))
            .collect::<Vec<_>>();
        self.add_tracks(tracks);
        self
    }

    pub fn update_with_sc_playlist(&mut self, playlist: &soundcloud::Playlist) -> &mut Playlist {
        self.provider      = Provider::SoundCloud;
        self.identifier    = playlist.id.to_string();
        self.owner_id      = Some(playlist.user.id.to_string());
        self.owner_name    = Some(playlist.user.username.clone());
        self.url           = playlist.permalink_url.to_string();
        self.title         = playlist.title.to_string();
        self.description   = None;
        self.thumbnail_url = playlist.artwork_url.clone();
        self.artwork_url   = playlist.artwork_url.clone();
        self.state         = State::Alive;
        match DateTime::parse_from_str(&playlist.created_at, "%Y/%m/%d %H:%M:%S %z") {
            Ok(published_at) => self.published_at = published_at.naive_utc(),
            Err(_)           => (),
        };
        let tracks = playlist.tracks.iter()
            .map(|ref t| Track::from_sc_track(t))
            .collect::<Vec<_>>();
        self.add_tracks(tracks);
        self
    }

    pub fn update_with_am_playlist(&mut self, playlist: &apple_music::Playlist) -> &mut Playlist {
        let curator = playlist.clone().relationships.map(|r| {
            r.curator.data.clone()
        }).unwrap_or(vec![]);
        self.provider      = Provider::AppleMusic;
        self.identifier    = playlist.id.clone();
        self.owner_id      = curator.first().map(|c| c.id.clone());
        self.owner_name    = playlist.attributes.curator_name.clone();
        self.url           = playlist.attributes.url.clone();
        self.title         = playlist.attributes.name.clone();
        self.description   = playlist.attributes.description.clone().and_then(|d| d.short.clone());
        self.thumbnail_url = playlist.attributes.artwork.clone().map(|a| a.url);
        self.artwork_url   = playlist.attributes.artwork.clone().map(|a| a.url);
        self.state         = State::Alive;
        self
    }

    pub fn disable(&mut self) -> &mut Playlist {
        self.state = State::Dead;
        self
    }

    pub fn delete(&self) -> Result<(), Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("DELETE FROM playlists WHERE id=$1"));
        let result = stmt.query(&[&self.id]);
        match result {
            Ok(_)  => Ok(()),
            Err(_) => Err(Error::Unexpected)
        }
    }
}

#[cfg(test)]
mod test {
    use model::enclosure::Enclosure;
    use model::Model;
    use super::Playlist;
    use Provider;
    #[test]
    fn test_new() {
        let playlist = Playlist::new(Provider::YouTube,
                                     "PLy8LZ8FM-o0ViuGAF68RAaXkQ8V-3dbTX".to_string());
        assert_eq!(playlist.provider, Provider::YouTube);
        assert_eq!(&playlist.identifier, "PLy8LZ8FM-o0ViuGAF68RAaXkQ8V-3dbTX")
    }
    #[test]
    fn test_find_of_create() {
        let identifier = "PLy8LZ8FM-o0ViuGAF68RAaXkQ8V-3dbTX".to_string();
        let result     = Playlist::find_or_create(Provider::YouTube, identifier);
        assert!(result.is_ok());
    }
    #[test]
    fn test_delete() {
        let identifier = "test_delete".to_string();
        let playlist   = Playlist::find_or_create(Provider::YouTube, identifier).unwrap();
        let result     = playlist.delete();
        assert!(result.is_ok());
    }
    #[test]
    fn test_save() {
        let id = "test_save";
        let mut playlist = Playlist::find_or_create(Provider::YouTube, id.to_string()).unwrap();
        playlist.title = "title".to_string();
        let result = playlist.save();
        assert!(result.is_ok());
        let playlist = Playlist::find_or_create(Provider::YouTube, id.to_string()).unwrap();
        assert_eq!(&playlist.title, "title");
    }
}
<|endoftext|>


<commit_before>use io;
use std::fs::File;

pub struct MultiFile {
    files_iterator: Box<Iterator<Item = String>>,
    current_file: Option<File>,
}

impl MultiFile {
    pub fn new(filenames: Box<Iterator<Item = String>>) -> MultiFile {
        MultiFile {
            files_iterator: filenames,
            current_file: None,
        }
    }
}

impl io::Read for MultiFile {
    fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
        let read_size;
        {
            let mut file = match self.current_file {
                Some(ref file) => file,
                None => {
                    println!("No file yet");
                    self.current_file = Some(File::open(&self.files_iterator.next().unwrap())?);
                    println!("Opened file {:#?}", &self.current_file);
                    return self.read(&mut buf);
                }
            };
            read_size = file.read(buf);
        }

        match read_size {
            Ok(0) => {
                println!("Read 0 bytes, current file {:#?}", &self.current_file);
                self.current_file = match &self.files_iterator.next() {
                    Some(file) => Some(File::open(file).unwrap()),
                    None => {
                        return Ok(0);
                    }
                };
                println!("Opened file {:#?}", &self.current_file);
                return self.read(&mut buf);
            }
            Ok(read_size) => Ok(read_size),
            Err(err) => Err(err),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::Read;
    use std::io::BufRead;

    use super::*;

    #[test]
    fn test_instantiate() {
        let filenames = Box::new(
            vec![
                String::from("src/test/simple-1.log"),
                String::from("src/test/simple-2.log"),
            ].into_iter(),
        );
        let _input = MultiFile::new(filenames);
    }

    #[test]
    fn test_read_all() {
        let filenames = Box::new(
            vec![
                String::from("src/test/simple-1.log"),
                String::from("src/test/simple-2.log"),
            ].into_iter(),
        );
        let input = MultiFile::new(filenames);

        let reader = io::BufReader::new(input);

        let result = reader.lines().count();
        assert_eq!(result, 8);
    }

    #[test]
    fn test_read_non_existent() {
        let filenames = Box::new(vec![String::from("src/test/non-existent.log")].into_iter());
        let mut input = MultiFile::new(filenames);
        let mut buffer = [0; 10];
        let result = input.read(&mut buffer);

        assert!(result.is_err());
    }
}
<commit_msg>Remove debugging statements<commit_after>use io;
use std::fs::File;

pub struct MultiFile {
    files_iterator: Box<Iterator<Item = String>>,
    current_file: Option<File>,
}

impl MultiFile {
    pub fn new(filenames: Box<Iterator<Item = String>>) -> MultiFile {
        MultiFile {
            files_iterator: filenames,
            current_file: None,
        }
    }
}

impl io::Read for MultiFile {
    fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
        let read_size;
        {
            let mut file = match self.current_file {
                Some(ref file) => file,
                None => {
                    self.current_file = Some(File::open(&self.files_iterator.next().unwrap())?);
                    return self.read(&mut buf);
                }
            };
            read_size = file.read(buf);
        }

        match read_size {
            Ok(0) => {
                self.current_file = match &self.files_iterator.next() {
                    Some(file) => Some(File::open(file).unwrap()),
                    None => {
                        return Ok(0);
                    }
                };
                return self.read(&mut buf);
            }
            Ok(read_size) => Ok(read_size),
            Err(err) => Err(err),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::Read;
    use std::io::BufRead;

    use super::*;

    #[test]
    fn test_instantiate() {
        let filenames = Box::new(
            vec![
                String::from("src/test/simple-1.log"),
                String::from("src/test/simple-2.log"),
            ].into_iter(),
        );
        let _input = MultiFile::new(filenames);
    }

    #[test]
    fn test_read_all() {
        let filenames = Box::new(
            vec![
                String::from("src/test/simple-1.log"),
                String::from("src/test/simple-2.log"),
            ].into_iter(),
        );
        let input = MultiFile::new(filenames);

        let reader = io::BufReader::new(input);

        let result = reader.lines().count();
        assert_eq!(result, 8);
    }

    #[test]
    fn test_read_non_existent() {
        let filenames = Box::new(vec![String::from("src/test/non-existent.log")].into_iter());
        let mut input = MultiFile::new(filenames);
        let mut buffer = [0; 10];
        let result = input.read(&mut buffer);

        assert!(result.is_err());
    }
}
<|endoftext|>


<commit_before>#![feature(iterator_step_by)]

use std::io;
use std::io::prelude::*;

fn create_hash(
    hash_lenght: usize,
    num_hash_rounds: usize,
    skip_lenghts: &Vec<usize>,
) -> Vec<usize> {

    let mut out: Vec<usize> = (0..hash_lenght).collect();
    let mut curr_pos = 0;
    let mut skip_len = 0;

    for _ in 0..num_hash_rounds {
        for in_skip_len in skip_lenghts {

            let end_pos = curr_pos + in_skip_len;

            let tmp_vec = if end_pos <= out.len() {
                out[curr_pos..end_pos].to_vec()
            } else {
                let mut tmp = out[curr_pos..].to_vec();

                tmp.extend(out[0..(end_pos % out.len())].to_vec());

                tmp
            };

            for (i, val) in tmp_vec.into_iter().rev().enumerate() {
                let l = out.len();
                out[(curr_pos + i) % l] = val;
            }

            curr_pos = (end_pos + skip_len) % out.len();
            skip_len += 1;
        }
    }

    out
}

fn create_full_hash(input_str: &str) -> String {
    let mut skip_lenghts: Vec<usize> = input_str.chars().map(|ch| ch as usize).collect();
    skip_lenghts.extend(vec![17, 31, 73, 47, 23]);

    let sparse_hash = create_hash(256, 64, &skip_lenghts);

    sparse_hash
        .windows(16)
        .step_by(16)
        .map(|window| {
            format!(
                "{:02x}",
                window.into_iter().fold(0, |acc, ch| acc ^ (*ch as u8))
            )
        })
        .collect()
}

fn main() {
    let mut input_str = String::new();
    io::stdin().read_to_string(&mut input_str).unwrap();

    let inputs = input_str
        .trim()
        .split(",")
        .map(|len_str| len_str.parse())
        .collect::<Result<Vec<usize>, _>>()
        .expect("parsing error");

    let hash = create_hash(256, 1, &inputs);
    println!("Part A: {}", hash[0] * hash[1]);

    println!("Part B: {}", create_full_hash(&input_str.trim()));
}

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

    #[test]
    fn create_hash_test() {
        assert_eq!(vec![3, 4, 2, 1, 0], create_hash(5, 1, &vec![3, 4, 1, 5]));
    }

    #[test]
    fn full_hash_test() {
        assert_eq!("a2582a3a0e66e6e86e3812dcb672a272", create_full_hash(""));
        assert_eq!(
            "33efeb34ea91902bb2f59c9920caa6cd",
            create_full_hash("AoC 2017")
        );
        assert_eq!(
            "3efbe78a8d82f29979031a4aa0b16a9d",
            create_full_hash("1,2,3")
        );
        assert_eq!(
            "63960835bcdc130f0b66d7ff4f6a5a8e",
            create_full_hash("1,2,4")
        );
    }
}
<commit_msg>Modified day10/2017 for use by day14/2017<commit_after>#![feature(iterator_step_by)]

use std::io;
use std::io::prelude::*;

use std::env;

fn create_hash(
    hash_lenght: usize,
    num_hash_rounds: usize,
    skip_lenghts: &Vec<usize>,
) -> Vec<usize> {

    let mut out: Vec<usize> = (0..hash_lenght).collect();
    let mut curr_pos = 0;
    let mut skip_len = 0;

    for _ in 0..num_hash_rounds {
        for in_skip_len in skip_lenghts {

            let end_pos = curr_pos + in_skip_len;

            let tmp_vec = if end_pos <= out.len() {
                out[curr_pos..end_pos].to_vec()
            } else {
                let mut tmp = out[curr_pos..].to_vec();

                tmp.extend(out[0..(end_pos % out.len())].to_vec());

                tmp
            };

            for (i, val) in tmp_vec.into_iter().rev().enumerate() {
                let l = out.len();
                out[(curr_pos + i) % l] = val;
            }

            curr_pos = (end_pos + skip_len) % out.len();
            skip_len += 1;
        }
    }

    out
}

fn create_full_hash(input_str: &str) -> String {
    let mut skip_lenghts: Vec<usize> = input_str.chars().map(|ch| ch as usize).collect();
    skip_lenghts.extend(vec![17, 31, 73, 47, 23]);

    let sparse_hash = create_hash(256, 64, &skip_lenghts);

    sparse_hash
        .windows(16)
        .step_by(16)
        .map(|window| {
            format!(
                "{:02x}",
                window.into_iter().fold(0, |acc, ch| acc ^ (*ch as u8))
            )
        })
        .collect()
}

fn main() {

    let mut args = env::args();
    args.next();

    if let Some(arg) = args.next() {
        match arg.as_str() {
            "-a" => {
                let mut input_str = String::new();
                io::stdin().read_to_string(&mut input_str).unwrap();

                let inputs = input_str
                    .trim()
                    .split(",")
                    .map(|len_str| len_str.parse())
                    .collect::<Result<Vec<usize>, _>>()
                    .expect("parsing error");

                let hash = create_hash(256, 1, &inputs);
                println!("{}", hash[0] * hash[1]);
            },
            "-b" => {

                let input_str = if let Some(hash) = args.next() {
                    hash
                } else {
                    let mut tmp = String::new();
                    io::stdin().read_to_string(&mut tmp).unwrap();
                    tmp
                };

                println!("{}", create_full_hash(&input_str.trim()));
            },
            _ => {panic!("Use -a or -b argument to specify the part of the puzzle.");}
        }
    } else {
        panic!("Use -a or -b argument to specify the part of the puzzle.");
    }
}

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

    #[test]
    fn create_hash_test() {
        assert_eq!(vec![3, 4, 2, 1, 0], create_hash(5, 1, &vec![3, 4, 1, 5]));
    }

    #[test]
    fn full_hash_test() {
        assert_eq!("a2582a3a0e66e6e86e3812dcb672a272", create_full_hash(""));
        assert_eq!(
            "33efeb34ea91902bb2f59c9920caa6cd",
            create_full_hash("AoC 2017")
        );
        assert_eq!(
            "3efbe78a8d82f29979031a4aa0b16a9d",
            create_full_hash("1,2,3")
        );
        assert_eq!(
            "63960835bcdc130f0b66d7ff4f6a5a8e",
            create_full_hash("1,2,4")
        );
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015-2016 Ben Ashford
 *
 * 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.
 */

//! Implementations of specific ElasticSearch operations
//!
//! The various methods on [`Client`](../struct.Client.html) are entry points to
//! ElasticSearch's set of operations.  This module, and it's child modules are
//! the implementation of those operations.

use std::borrow::Cow;

use ::util::StrJoin;

// Specific operations
#[macro_use]
pub mod common;

pub mod bulk;
pub mod delete;
pub mod delete_index;
pub mod get;
pub mod index;
pub mod refresh;
pub mod search;
pub mod analyze;
pub mod mapping;
pub mod version;

// Common utility functions

/// A repeating convention in the ElasticSearch REST API is parameters that can
/// take multiple values
fn format_multi(parts: &[&str]) -> Cow<'static, str> {
    if parts.is_empty() {
        Cow::Borrowed("_all")
    } else {
        Cow::Owned(parts.iter().join(","))
    }
}

/// Multiple operations require indexes and types to be specified, there are
/// rules for combining the two however.  E.g. all indexes is specified with
/// `_all`, but all types are specified by omitting type entirely.
fn format_indexes_and_types(indexes: &[&str], types: &[&str]) -> Cow<'static, str> {
    if types.is_empty() {
        format_multi(indexes)
    } else {
        Cow::Owned(format!("{}/{}", format_multi(indexes), format_multi(types)))
    }
}

// Results

/// Shared struct for operations that include counts of success/failed shards.
/// This is returned within various other result structs.
#[derive(Debug, Deserialize)]
pub struct ShardCountResult {
    pub total:      u64,
    pub successful: u64,
    pub failed:     u64
}

#[derive(Debug, Deserialize)]
pub struct GenericResult {
    pub acknowledged: bool
}
<commit_msg>Require fewer temporary Strings<commit_after>/*
 * Copyright 2015-2016 Ben Ashford
 *
 * 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.
 */

//! Implementations of specific ElasticSearch operations
//!
//! The various methods on [`Client`](../struct.Client.html) are entry points to
//! ElasticSearch's set of operations.  This module, and it's child modules are
//! the implementation of those operations.

use std::borrow::Cow;

use ::util::StrJoin;

// Specific operations
#[macro_use]
pub mod common;

pub mod bulk;
pub mod delete;
pub mod delete_index;
pub mod get;
pub mod index;
pub mod refresh;
pub mod search;
pub mod analyze;
pub mod mapping;
pub mod version;

// Common utility functions

/// A repeating convention in the ElasticSearch REST API is parameters that can
/// take multiple values
fn format_multi<'a>(parts: &[&'a str]) -> Cow<'a, str> {
    match parts.len() {
        0 => Cow::Borrowed("_all"),
        1 => Cow::Borrowed(parts[0]),
        _ => Cow::Owned(parts.iter().join(","))
    }
}

/// Multiple operations require indexes and types to be specified, there are
/// rules for combining the two however.  E.g. all indexes is specified with
/// `_all`, but all types are specified by omitting type entirely.
fn format_indexes_and_types<'a>(indexes: &[&'a str], types: &[&str]) -> Cow<'a, str> {
    if types.is_empty() {
        format_multi(indexes)
    } else {
        Cow::Owned(format!("{}/{}", format_multi(indexes), format_multi(types)))
    }
}

// Results

/// Shared struct for operations that include counts of success/failed shards.
/// This is returned within various other result structs.
#[derive(Debug, Deserialize)]
pub struct ShardCountResult {
    pub total:      u64,
    pub successful: u64,
    pub failed:     u64
}

#[derive(Debug, Deserialize)]
pub struct GenericResult {
    pub acknowledged: bool
}
<|endoftext|>


<commit_before><commit_msg>Added schema<commit_after><|endoftext|>


<commit_before><commit_msg>serde: Fix int_or_string_to_int deserialization helper<commit_after><|endoftext|>


<commit_before>/// This function is where the kernel sets up IRQ handlers
/// It is increcibly unsafe, and should be minimal in nature
/// It must create the IDT with the correct entries, those entries are
/// defined in other files inside of the `arch` module

use core::slice;
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};

use crate::memory::{Frame};
use crate::paging::{ActivePageTable, PageTableType, Page, PAGE_SIZE, PhysicalAddress, VirtualAddress};
use crate::paging::entry::{EntryFlags};

use crate::allocator;
use crate::device;
use crate::init::device_tree;
use crate::interrupt;
use crate::log::{self, info};
use crate::paging;

/// Test of zero values in BSS.
static BSS_TEST_ZERO: usize = 0;
/// Test of non-zero values in data.
static DATA_TEST_NONZERO: usize = 0xFFFF_FFFF_FFFF_FFFF;
/// Test of zero values in thread BSS
#[thread_local]
static mut TBSS_TEST_ZERO: usize = 0;
/// Test of non-zero values in thread data.
#[thread_local]
static mut TDATA_TEST_NONZERO: usize = 0xFFFF_FFFF_FFFF_FFFF;

pub static KERNEL_BASE: AtomicUsize = AtomicUsize::new(0);
pub static KERNEL_SIZE: AtomicUsize = AtomicUsize::new(0);
pub static CPU_COUNT: AtomicUsize = AtomicUsize::new(0);
pub static AP_READY: AtomicBool = AtomicBool::new(false);
static BSP_READY: AtomicBool = AtomicBool::new(false);

#[repr(packed)]
pub struct KernelArgs {
    kernel_base: u64,
    kernel_size: u64,
    stack_base: u64,
    stack_size: u64,
    env_base: u64,
    env_size: u64,
    dtb_base: u64,
    dtb_size: u64,
}

/// The entry to Rust, all things must be initialized
#[no_mangle]
pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
    let env = {
        let args = &*args_ptr;

        let kernel_base = args.kernel_base as usize;
        let kernel_size = args.kernel_size as usize;
        let stack_base = args.stack_base as usize;
        let stack_size = args.stack_size as usize;
        let env_base = args.env_base as usize;
        let env_size = args.env_size as usize;
        let dtb_base = args.dtb_base as usize;
        let dtb_size = args.dtb_size as usize;

        //TODO: remove this hack for early console, use device tree
        {
            let mut serial = device::uart_pl011::SerialPort::new(crate::KERNEL_DEVMAP_OFFSET + 0x9000000);
            serial.init(false);
            serial.send(b'T');
            serial.send(b'E');
            serial.send(b'S');
            serial.send(b'T');
            serial.send(b'\r');
            serial.send(b'\n');
            *device::serial::COM1.lock() = Some(serial);
        }

        // BSS should already be zero
        {
            assert_eq!(BSS_TEST_ZERO, 0);
            assert_eq!(DATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
        }

        KERNEL_BASE.store(kernel_base, Ordering::SeqCst);
        KERNEL_SIZE.store(kernel_size, Ordering::SeqCst);

        // Initialize logger
        log::init_logger(|r| {
            use core::fmt::Write;
            let _ = write!(
                crate::debug::Writer::new(),
                "{}:{} -- {}\n",
                r.target(),
                r.level(),
                r.args()
            );
        });

        info!("Redox OS starting...");
        info!("Kernel: {:X}:{:X}", kernel_base, kernel_base + kernel_size);
        info!("Stack: {:X}:{:X}", stack_base, stack_base + stack_size);
        info!("Env: {:X}:{:X}", env_base, env_base + env_size);
        info!("DTB: {:X}:{:X}", dtb_base, dtb_base + dtb_size);

        //TODO: Until fixed, the DTB is at DEVMAP_OFFSET + dtb_base
        // This is not required after paging is enabled because paging fixes this
        device_tree::fill_memory_map(crate::KERNEL_DEVMAP_OFFSET + dtb_base, dtb_size);
        let env_size = device_tree::fill_env_data(crate::KERNEL_DEVMAP_OFFSET + dtb_base, dtb_size, env_base);

        // Initialize RMM
        println!("RMM INIT START");
        crate::arch::rmm::init(kernel_base, kernel_size + stack_size);
        println!("RMM INIT COMPLETE");

        // Initialize paging
        println!("PAGING INIT START");
        let (mut active_table, _tcb_offset) = paging::init(0);
        println!("PAGING INIT COMPLETE");

        // Test tdata and tbss
        {
            assert_eq!(TBSS_TEST_ZERO, 0);
            TBSS_TEST_ZERO += 1;
            assert_eq!(TBSS_TEST_ZERO, 1);
            assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
            TDATA_TEST_NONZERO -= 1;
            assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFE);
        }

        // Reset AP variables
        CPU_COUNT.store(1, Ordering::SeqCst);
        AP_READY.store(false, Ordering::SeqCst);
        BSP_READY.store(false, Ordering::SeqCst);

        // Setup kernel heap
        println!("ALLOCATOR INIT START");
        allocator::init(&mut active_table);
        println!("ALLOCATOR INIT COMPLETE");

        // Activate memory logging
        println!("LOG INIT START");
        log::init();
        println!("LOG INIT COMPLETE");

        // Initialize devices
        println!("DEVICE INIT START");
        device::init(&mut active_table);
        println!("DEVICE INIT COMPLETE");

        // Initialize all of the non-core devices not otherwise needed to complete initialization
        println!("DEVICE INIT NONCORE START");
        device::init_noncore();
        println!("DEVICE INIT NONCORE COMPLETE");

        BSP_READY.store(true, Ordering::SeqCst);

        slice::from_raw_parts(env_base as *const u8, env_size)
    };

    println!("KMAIN");
    crate::kmain(CPU_COUNT.load(Ordering::SeqCst), env);
}

#[repr(packed)]
pub struct KernelArgsAp {
    cpu_id: u64,
    page_table: u64,
    stack_start: u64,
    stack_end: u64,
}

/// Entry to rust for an AP
pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
    loop{}
}

#[naked]
pub unsafe fn usermode(ip: usize, sp: usize, arg: usize, singlestep: bool) -> ! {
    let cpu_id: usize = 0;
    let uspace_tls_start = (crate::USER_TLS_OFFSET + crate::USER_TLS_SIZE * cpu_id);
    let spsr: u32 = 0;

    llvm_asm!("msr   tpidr_el0, $0" : : "r"(uspace_tls_start) : : "volatile");
    llvm_asm!("msr   spsr_el1, $0" : : "r"(spsr) : : "volatile");
    llvm_asm!("msr   elr_el1, $0" : : "r"(ip) : : "volatile");
    llvm_asm!("msr   sp_el0, $0" : : "r"(sp) : : "volatile");

    llvm_asm!("mov   x0, $0" : : "r"(arg) : : "volatile");
    llvm_asm!("eret" : : : : "volatile");

    unreachable!();
}
<commit_msg>aarch64: usermode: Remove tpidr_el0 manipulation<commit_after>/// This function is where the kernel sets up IRQ handlers
/// It is increcibly unsafe, and should be minimal in nature
/// It must create the IDT with the correct entries, those entries are
/// defined in other files inside of the `arch` module

use core::slice;
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};

use crate::memory::{Frame};
use crate::paging::{ActivePageTable, PageTableType, Page, PAGE_SIZE, PhysicalAddress, VirtualAddress};
use crate::paging::entry::{EntryFlags};

use crate::allocator;
use crate::device;
use crate::init::device_tree;
use crate::interrupt;
use crate::log::{self, info};
use crate::paging;

/// Test of zero values in BSS.
static BSS_TEST_ZERO: usize = 0;
/// Test of non-zero values in data.
static DATA_TEST_NONZERO: usize = 0xFFFF_FFFF_FFFF_FFFF;
/// Test of zero values in thread BSS
#[thread_local]
static mut TBSS_TEST_ZERO: usize = 0;
/// Test of non-zero values in thread data.
#[thread_local]
static mut TDATA_TEST_NONZERO: usize = 0xFFFF_FFFF_FFFF_FFFF;

pub static KERNEL_BASE: AtomicUsize = AtomicUsize::new(0);
pub static KERNEL_SIZE: AtomicUsize = AtomicUsize::new(0);
pub static CPU_COUNT: AtomicUsize = AtomicUsize::new(0);
pub static AP_READY: AtomicBool = AtomicBool::new(false);
static BSP_READY: AtomicBool = AtomicBool::new(false);

#[repr(packed)]
pub struct KernelArgs {
    kernel_base: u64,
    kernel_size: u64,
    stack_base: u64,
    stack_size: u64,
    env_base: u64,
    env_size: u64,
    dtb_base: u64,
    dtb_size: u64,
}

/// The entry to Rust, all things must be initialized
#[no_mangle]
pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
    let env = {
        let args = &*args_ptr;

        let kernel_base = args.kernel_base as usize;
        let kernel_size = args.kernel_size as usize;
        let stack_base = args.stack_base as usize;
        let stack_size = args.stack_size as usize;
        let env_base = args.env_base as usize;
        let env_size = args.env_size as usize;
        let dtb_base = args.dtb_base as usize;
        let dtb_size = args.dtb_size as usize;

        //TODO: remove this hack for early console, use device tree
        {
            let mut serial = device::uart_pl011::SerialPort::new(crate::KERNEL_DEVMAP_OFFSET + 0x9000000);
            serial.init(false);
            serial.send(b'T');
            serial.send(b'E');
            serial.send(b'S');
            serial.send(b'T');
            serial.send(b'\r');
            serial.send(b'\n');
            *device::serial::COM1.lock() = Some(serial);
        }

        // BSS should already be zero
        {
            assert_eq!(BSS_TEST_ZERO, 0);
            assert_eq!(DATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
        }

        KERNEL_BASE.store(kernel_base, Ordering::SeqCst);
        KERNEL_SIZE.store(kernel_size, Ordering::SeqCst);

        // Initialize logger
        log::init_logger(|r| {
            use core::fmt::Write;
            let _ = write!(
                crate::debug::Writer::new(),
                "{}:{} -- {}\n",
                r.target(),
                r.level(),
                r.args()
            );
        });

        info!("Redox OS starting...");
        info!("Kernel: {:X}:{:X}", kernel_base, kernel_base + kernel_size);
        info!("Stack: {:X}:{:X}", stack_base, stack_base + stack_size);
        info!("Env: {:X}:{:X}", env_base, env_base + env_size);
        info!("DTB: {:X}:{:X}", dtb_base, dtb_base + dtb_size);

        //TODO: Until fixed, the DTB is at DEVMAP_OFFSET + dtb_base
        // This is not required after paging is enabled because paging fixes this
        device_tree::fill_memory_map(crate::KERNEL_DEVMAP_OFFSET + dtb_base, dtb_size);
        let env_size = device_tree::fill_env_data(crate::KERNEL_DEVMAP_OFFSET + dtb_base, dtb_size, env_base);

        // Initialize RMM
        println!("RMM INIT START");
        crate::arch::rmm::init(kernel_base, kernel_size + stack_size);
        println!("RMM INIT COMPLETE");

        // Initialize paging
        println!("PAGING INIT START");
        let (mut active_table, _tcb_offset) = paging::init(0);
        println!("PAGING INIT COMPLETE");

        // Test tdata and tbss
        {
            assert_eq!(TBSS_TEST_ZERO, 0);
            TBSS_TEST_ZERO += 1;
            assert_eq!(TBSS_TEST_ZERO, 1);
            assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
            TDATA_TEST_NONZERO -= 1;
            assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFE);
        }

        // Reset AP variables
        CPU_COUNT.store(1, Ordering::SeqCst);
        AP_READY.store(false, Ordering::SeqCst);
        BSP_READY.store(false, Ordering::SeqCst);

        // Setup kernel heap
        println!("ALLOCATOR INIT START");
        allocator::init(&mut active_table);
        println!("ALLOCATOR INIT COMPLETE");

        // Activate memory logging
        println!("LOG INIT START");
        log::init();
        println!("LOG INIT COMPLETE");

        // Initialize devices
        println!("DEVICE INIT START");
        device::init(&mut active_table);
        println!("DEVICE INIT COMPLETE");

        // Initialize all of the non-core devices not otherwise needed to complete initialization
        println!("DEVICE INIT NONCORE START");
        device::init_noncore();
        println!("DEVICE INIT NONCORE COMPLETE");

        BSP_READY.store(true, Ordering::SeqCst);

        slice::from_raw_parts(env_base as *const u8, env_size)
    };

    println!("KMAIN");
    crate::kmain(CPU_COUNT.load(Ordering::SeqCst), env);
}

#[repr(packed)]
pub struct KernelArgsAp {
    cpu_id: u64,
    page_table: u64,
    stack_start: u64,
    stack_end: u64,
}

/// Entry to rust for an AP
pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
    loop{}
}

#[naked]
pub unsafe fn usermode(ip: usize, sp: usize, arg: usize, singlestep: bool) -> ! {
    let cpu_id: usize = 0;
    let spsr: u32 = 0;

    llvm_asm!("msr   spsr_el1, $0" : : "r"(spsr) : : "volatile");
    llvm_asm!("msr   elr_el1, $0" : : "r"(ip) : : "volatile");
    llvm_asm!("msr   sp_el0, $0" : : "r"(sp) : : "volatile");

    llvm_asm!("mov   x0, $0" : : "r"(arg) : : "volatile");
    llvm_asm!("eret" : : : : "volatile");

    unreachable!();
}
<|endoftext|>


<commit_before><commit_msg>add fn CodepointInfo::new() -> CodepointInfo<commit_after><|endoftext|>


<commit_before>//! Types used in the registry.

use std::sync::Arc;
use std::fmt::{Debug, Formatter};
use std::fmt::Result as FmtResult;

use rustc_serialize::json::Json;

bitflags! {
    /// Access permissions for items in the registry
    pub flags AccessFlags: u8 {
        /// Clients can read/get the data
        const READ    = 1 << 0,
        /// Clients can write/set the data
        const WRITE   = 1 << 1,
    }
}

impl AccessFlags {
    /// Read permissions
    #[inline]
    #[allow(non_snake_case)]
    pub fn READ() -> AccessFlags { READ }

    /// Write permissions
    #[inline]
    #[allow(non_snake_case)]
    pub fn WRITE() -> AccessFlags { WRITE }
}

/// Function which will yield an object
pub type GetFn = Arc<Fn() -> Json + Send + Sync>;

/// Function which will set an object
pub type SetFn = Arc<Fn(Json) + Send + Sync>;

/// Enum of types of registry fields
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum FieldType { Object, Property }

/// Data which can be stored in the registry
#[derive(Clone)]
pub enum RegistryField {
    /// An object with permission flags
    Object {
        /// Permission flags for Lua get/setting the value
        flags: AccessFlags,
        /// Data associated with this value
        data: Arc<Json>
    },
    /// A registry value whose get and set maps to other Rust code
    Property {
        /// Method called to set a property
        get: Option<GetFn>,
        /// Method called to set a property
        set: Option<SetFn>
    },
}

/// Result of what can be accessed from a registry value.
#[derive(Clone)]
pub enum RegistryGetData {
    /// An object in the registry
    Object(AccessFlags, Arc<Json>),
    /// Get field of a property in the registry
    Property(AccessFlags, GetFn)
}

/// Result of what can be set to a registry value.
#[derive(Clone)]
pub enum RegistrySetData {
    /// Some data was displaced, here it is
    Displaced(Arc<Json>),
    /// A property was retrieved, you should run it
    Property(AccessFlags, SetFn)
}

impl Debug for RegistryField {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match self {
            &RegistryField::Object { ref flags, ref data } =>
                f.debug_struct("RegistryField::Object")
                .field("flags", flags as &Debug)
                .field("data", data as &Debug).finish(),
            &RegistryField::Property { ref get, ref set } => {
                let new_get = match get { &Some(_) => Some(true), &None => None };
                let new_set = match set { &Some(_) => Some(true), &None => None };
                f.debug_struct("RegistryField::Property")
                    .field("get", &new_get)
                    .field("set", &new_set)
                    .finish()
            }
        }
    }
}

impl Debug for RegistryGetData {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match self {
            &RegistryGetData::Object(ref flags, ref data) =>
                f.debug_struct("RegistryGetData::Object")
                .field("flags", flags as &Debug)
                .field("data", data as &Debug).finish(),
            &RegistryGetData::Property(ref flags, _) =>
                write!(f, "RegistryGetData::Property({:?})", flags)
        }
    }
}

impl Debug for RegistrySetData {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match self {
            &RegistrySetData::Displaced(ref data) =>
                f.debug_struct("RegistrySetData::Displaced")
                .field("data", data as &Debug).finish(),
            &RegistrySetData::Property(_, _) =>
                write!(f, "RegistrySetData::Property(...)")
        }
    }
}

impl RegistryField {
    /// Converts this RegistryField to maybe an object. Does not call property methods.
    pub fn as_object(self) -> Option<(AccessFlags, Arc<Json>)> {
        match self {
            RegistryField::Object { flags, data } => Some((flags, data)),
            _ => None
        }
    }

    /// Gets this field as maybe a property with maybe a getter and setter.
    pub fn as_property(self) -> Option<(Option<GetFn>, Option<SetFn>)> {
        match self {
            RegistryField::Property { get, set } => Some((get, set)),
            _ => None
        }
    }

    /// Returns the getter, if this field is a property with a getter.
    #[allow(dead_code)]
    pub fn as_property_get(self) -> Option<GetFn> {
        self.as_property().and_then(|(maybe_get, _)| maybe_get)
    }

    /// Returns a setter if this field is a property with a setter.
    pub fn as_property_set(self) -> Option<SetFn> {
        self.as_property().and_then(|(_, maybe_set)| maybe_set)
    }

    /// Gets the type of this registry field
    pub fn get_type(&self) -> FieldType {
        match self {
            &RegistryField::Object { .. }   => FieldType::Object,
            &RegistryField::Property { .. } => FieldType::Property,
        }
    }

    /// Gets the set of AccessFlags needed for a registry field with said
    /// options
    pub fn get_flags(&self) -> AccessFlags {
        match *self {
            RegistryField::Object { ref flags, .. } => flags.clone(),
            RegistryField::Property { ref get, ref set } => {
                let mut flags = AccessFlags::empty();
                if get.is_some() { flags.insert(AccessFlags::READ()) }
                if set.is_some() { flags.insert(AccessFlags::WRITE()) }
                flags
            }
        }
    }
}

impl RegistryGetData {
    /// Collapses the waveform.
    ///
    /// If this is a Json, returns the Json data. If this is a property, runs the
    /// method and returns the output.
    pub fn resolve(self) -> (AccessFlags, Arc<Json>) {
        match self {
            RegistryGetData::Object(flags, data) => (flags, data),
            RegistryGetData::Property(flags, get) =>
                (flags, Arc::new(get()))
        }
    }

    /// Gets the FieldType of this GetData (property or object)
    #[allow(dead_code)]
    pub fn get_type(&self) -> FieldType {
        match self {
            &RegistryGetData::Property(_, _) => FieldType::Property,
            &RegistryGetData::Object(_, _) => FieldType::Object
        }
    }
}

impl RegistrySetData {
    /// If this set data is a property, calls the property
    pub fn call(self, json: Json) {
        match self {
            RegistrySetData::Displaced(_) => (),
            RegistrySetData::Property(_flags, set) => set(json)
        }
    }

    /// Gets the FieldType of this SetData (property or object)
    #[allow(dead_code)]
    pub fn get_type(&self) -> FieldType {
        match *self {
            RegistrySetData::Displaced(_) => FieldType::Object,
            RegistrySetData::Property(_, _) => FieldType::Property
        }
    }
}

#[cfg(test)]
mod tests {
    use std::sync::Arc;
    use rustc_serialize::json::Json;
    use super::*;

    #[test]
    fn registry_field_debug() {
        let field_obj = RegistryField::Object {
            flags: AccessFlags::READ(),
            data: Arc::new(Json::String("foo".to_string()))
        };
        let field_prop = RegistryField::Property { get: None, set: None };

        assert_eq!(format!("{:?}", field_obj),
            "RegistryField::Object { flags: READ, data: String(\"foo\") }");
        assert_eq!(format!("{:?}", field_prop),
                   "RegistryField::Property { get: None, set: None }");
    }

    #[test]
    fn registry_get_data_debug() {
        let get_obj = RegistryGetData::Object(
            AccessFlags::READ(), Arc::new(Json::String("foo".to_string())));
        assert_eq!(format!("{:?}", get_obj),
              "RegistryGetData::Object { flags: READ, data: String(\"foo\") }");
    }
}
<commit_msg>Added Registry{get/set}Data tests<commit_after>//! Types used in the registry.

use std::sync::Arc;
use std::fmt::{Debug, Formatter};
use std::fmt::Result as FmtResult;

use rustc_serialize::json::Json;

bitflags! {
    /// Access permissions for items in the registry
    pub flags AccessFlags: u8 {
        /// Clients can read/get the data
        const READ    = 1 << 0,
        /// Clients can write/set the data
        const WRITE   = 1 << 1,
    }
}

impl AccessFlags {
    /// Read permissions
    #[inline]
    #[allow(non_snake_case)]
    pub fn READ() -> AccessFlags { READ }

    /// Write permissions
    #[inline]
    #[allow(non_snake_case)]
    pub fn WRITE() -> AccessFlags { WRITE }
}

/// Function which will yield an object
pub type GetFn = Arc<Fn() -> Json + Send + Sync>;

/// Function which will set an object
pub type SetFn = Arc<Fn(Json) + Send + Sync>;

/// Enum of types of registry fields
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum FieldType { Object, Property }

/// Data which can be stored in the registry
#[derive(Clone)]
pub enum RegistryField {
    /// An object with permission flags
    Object {
        /// Permission flags for Lua get/setting the value
        flags: AccessFlags,
        /// Data associated with this value
        data: Arc<Json>
    },
    /// A registry value whose get and set maps to other Rust code
    Property {
        /// Method called to set a property
        get: Option<GetFn>,
        /// Method called to set a property
        set: Option<SetFn>
    },
}

/// Result of what can be accessed from a registry value.
#[derive(Clone)]
pub enum RegistryGetData {
    /// An object in the registry
    Object(AccessFlags, Arc<Json>),
    /// Get field of a property in the registry
    Property(AccessFlags, GetFn)
}

/// Result of what can be set to a registry value.
#[derive(Clone)]
pub enum RegistrySetData {
    /// Some data was displaced, here it is
    Displaced(Arc<Json>),
    /// A property was retrieved, you should run it
    Property(AccessFlags, SetFn)
}

impl Debug for RegistryField {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match self {
            &RegistryField::Object { ref flags, ref data } =>
                f.debug_struct("RegistryField::Object")
                .field("flags", flags as &Debug)
                .field("data", data as &Debug).finish(),
            &RegistryField::Property { ref get, ref set } => {
                let new_get = match get { &Some(_) => Some(true), &None => None };
                let new_set = match set { &Some(_) => Some(true), &None => None };
                f.debug_struct("RegistryField::Property")
                    .field("get", &new_get)
                    .field("set", &new_set)
                    .finish()
            }
        }
    }
}

impl Debug for RegistryGetData {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match self {
            &RegistryGetData::Object(ref flags, ref data) =>
                f.debug_struct("RegistryGetData::Object")
                .field("flags", flags as &Debug)
                .field("data", data as &Debug).finish(),
            &RegistryGetData::Property(ref flags, _) =>
                write!(f, "RegistryGetData::Property({:?})", flags)
        }
    }
}

impl Debug for RegistrySetData {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match self {
            &RegistrySetData::Displaced(ref data) =>
                f.debug_struct("RegistrySetData::Displaced")
                .field("data", data as &Debug).finish(),
            &RegistrySetData::Property(_, _) =>
                write!(f, "RegistrySetData::Property(...)")
        }
    }
}

impl RegistryField {
    /// Converts this RegistryField to maybe an object. Does not call property methods.
    pub fn as_object(self) -> Option<(AccessFlags, Arc<Json>)> {
        match self {
            RegistryField::Object { flags, data } => Some((flags, data)),
            _ => None
        }
    }

    /// Gets this field as maybe a property with maybe a getter and setter.
    pub fn as_property(self) -> Option<(Option<GetFn>, Option<SetFn>)> {
        match self {
            RegistryField::Property { get, set } => Some((get, set)),
            _ => None
        }
    }

    /// Returns the getter, if this field is a property with a getter.
    #[allow(dead_code)]
    pub fn as_property_get(self) -> Option<GetFn> {
        self.as_property().and_then(|(maybe_get, _)| maybe_get)
    }

    /// Returns a setter if this field is a property with a setter.
    pub fn as_property_set(self) -> Option<SetFn> {
        self.as_property().and_then(|(_, maybe_set)| maybe_set)
    }

    /// Gets the type of this registry field
    pub fn get_type(&self) -> FieldType {
        match self {
            &RegistryField::Object { .. }   => FieldType::Object,
            &RegistryField::Property { .. } => FieldType::Property,
        }
    }

    /// Gets the set of AccessFlags needed for a registry field with said
    /// options
    pub fn get_flags(&self) -> AccessFlags {
        match *self {
            RegistryField::Object { ref flags, .. } => flags.clone(),
            RegistryField::Property { ref get, ref set } => {
                let mut flags = AccessFlags::empty();
                if get.is_some() { flags.insert(AccessFlags::READ()) }
                if set.is_some() { flags.insert(AccessFlags::WRITE()) }
                flags
            }
        }
    }
}

impl RegistryGetData {
    /// Collapses the waveform.
    ///
    /// If this is a Json, returns the Json data. If this is a property, runs the
    /// method and returns the output.
    pub fn resolve(self) -> (AccessFlags, Arc<Json>) {
        match self {
            RegistryGetData::Object(flags, data) => (flags, data),
            RegistryGetData::Property(flags, get) =>
                (flags, Arc::new(get()))
        }
    }

    /// Gets the FieldType of this GetData (property or object)
    #[allow(dead_code)]
    pub fn get_type(&self) -> FieldType {
        match self {
            &RegistryGetData::Property(_, _) => FieldType::Property,
            &RegistryGetData::Object(_, _) => FieldType::Object
        }
    }
}

impl RegistrySetData {
    /// If this set data is a property, calls the property
    pub fn call(self, json: Json) {
        match self {
            RegistrySetData::Displaced(_) => (),
            RegistrySetData::Property(_flags, set) => set(json)
        }
    }

    /// Gets the FieldType of this SetData (property or object)
    #[allow(dead_code)]
    pub fn get_type(&self) -> FieldType {
        match *self {
            RegistrySetData::Displaced(_) => FieldType::Object,
            RegistrySetData::Property(_, _) => FieldType::Property
        }
    }
}

#[cfg(test)]
mod tests {
    use std::sync::Arc;
    use rustc_serialize::json::Json;
    use super::*;

    #[test]
    fn registry_field_debug() {
        let field_obj = RegistryField::Object {
            flags: AccessFlags::READ(),
            data: Arc::new(Json::String("foo".to_string()))
        };
        let field_prop = RegistryField::Property { get: None, set: None };

        assert_eq!(format!("{:?}", field_obj),
            "RegistryField::Object { flags: READ, data: String(\"foo\") }");
        assert_eq!(format!("{:?}", field_prop),
                   "RegistryField::Property { get: None, set: None }");
    }

    #[test]
    fn registry_get_data_debug() {
        let get_obj = RegistryGetData::Object(
            AccessFlags::READ(), Arc::new(Json::String("foo".to_string())));
        assert_eq!(format!("{:?}", get_obj),
              "RegistryGetData::Object { flags: READ, data: String(\"foo\") }");
    }

    #[test]
    fn registry_field() {
        let prop = RegistryField::Property {
            get: None, set: None
        };
        assert_eq!(prop.get_type(), FieldType::Property);

        let null_field = RegistryField::Object {
            flags: AccessFlags::READ(),
            data: Arc::new(Json::Null)
        };

        /* Set Data */
        assert_eq!(null_field.get_type(), FieldType::Object);
        let null_data = null_field.clone().as_object().unwrap().1;
        assert_eq!(*null_data, Json::Null);
        let prop = RegistrySetData::Displaced(null_data);
        assert_eq!(prop.get_type(), FieldType::Object);

        // send function
        fn send(_json: Json) {}

        let set_prop = RegistrySetData::Property(AccessFlags::WRITE(),
                                                 Arc::new(send));
        assert_eq!(set_prop.get_type(), FieldType::Property);

        /* Get Data */
        assert_eq!(null_field.get_type(), FieldType::Object);
        let null_data = null_field.as_object().unwrap().1;
        assert_eq!(*null_data, Json::Null);
        let prop = RegistryGetData::Object(AccessFlags::READ(),
                                           null_data.clone());
        assert_eq!(prop.get_type(), FieldType::Object);

        // send function
        fn _get() -> Json { panic!()}

        let set_prop = RegistryGetData::Property(AccessFlags::WRITE(),
                                                 Arc::new(_get));
        assert_eq!(set_prop.get_type(), FieldType::Property);
    }
}
<|endoftext|>


<commit_before>pure fn fib(prev: uint, cur: uint) -> (uint, uint) {
    ret (cur, prev + cur);
}

fn main() {
    const MAX: uint = 4000000u;
    let mut (prev, cur) = (1u, 1u);
    let mut sum = 0u;
    while cur < MAX {
        if (cur % 2u == 0u) {
            sum += cur;
        }
        let (prev2, cur2) = fib(prev, cur);
        prev = prev2;
        cur = cur2;
    }
    io::println(#fmt("%u", sum));
}
<commit_msg>Use euler::calc::each_fib()<commit_after>use euler;

import euler::calc;

fn main() {
    const MAX: uint = 4000000u;
    let mut sum = 0u;
    for calc::each_fib {|f|
        if f >= MAX     { break; }
        if f % 2u == 0u { sum += f; }
    };
    io::println(#fmt("%u", sum));
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::iter::Iterator;

fn main() {
    println!("pub const INVALID_VALUE: u8 = 255;");

    // A-Z
    let standard_alphabet: Vec<u8> = (0x41..0x5B)
        // a-z
        .chain(0x61..0x7B)
        // 0-9
        .chain(0x30..0x3A)
        // +
        .chain(0x2B..0x2C)
        // /
        .chain(0x2F..0x30)
        .collect();
    print_encode_table(&standard_alphabet, "STANDARD_ENCODE", 0);
    print_decode_table(&standard_alphabet, "STANDARD_DECODE", 0);

    // A-Z
    let url_alphabet: Vec<u8> = (0x41..0x5B)
        // a-z
        .chain(0x61..0x7B)
        // 0-9
        .chain(0x30..0x3A)
        // -
        .chain(0x2D..0x2E)
        // _s
        .chain(0x5F..0x60)
        .collect();
    print_encode_table(&url_alphabet, "URL_SAFE_ENCODE", 0);
    print_decode_table(&url_alphabet, "URL_SAFE_DECODE", 0);
}

fn print_encode_table(alphabet: &[u8], const_name: &str, indent_depth: usize) {
    println!("#[cfg_attr(rustfmt, rustfmt_skip)]");
    println!(
        "{:width$}pub const {}: &'static [u8; 64] = &[",
        "",
        const_name,
        width = indent_depth
    );

    for (i, b) in alphabet.iter().enumerate() {
        println!(
            "{:width$}{}, // input {} (0x{:X}) => '{}' (0x{:X})",
            "",
            b,
            i,
            i,
            String::from_utf8(vec![*b as u8]).unwrap(),
            b,
            width = indent_depth + 4
        );
    }

    println!("{:width$}];", "", width = indent_depth);
}

fn print_decode_table(alphabet: &[u8], const_name: &str, indent_depth: usize) {
    // map of alphabet bytes to 6-bit morsels
    let mut input_to_morsel = HashMap::<u8, u8>::new();

    // standard base64 alphabet bytes, in order
    for (morsel, ascii_byte) in alphabet.iter().enumerate() {
        // truncation cast is fine here
        let _ = input_to_morsel.insert(*ascii_byte, morsel as u8);
    }

    println!("#[cfg_attr(rustfmt, rustfmt_skip)]");
    println!(
        "{:width$}pub const {}: &'static [u8; 256] = &[",
        "",
        const_name,
        width = indent_depth
    );
    for ascii_byte in 0..256 {
        let (value, comment) = match input_to_morsel.get(&(ascii_byte as u8)) {
            None => (
                "INVALID_VALUE".to_string(),
                format!("input {} (0x{:X})", ascii_byte, ascii_byte),
            ),
            Some(v) => (
                format!("{}", *v),
                format!(
                    "input {} (0x{:X} char '{}') => {} (0x{:X})",
                    ascii_byte,
                    ascii_byte,
                    String::from_utf8(vec![ascii_byte as u8]).unwrap(),
                    *v,
                    *v
                ),
            ),
        };

        println!(
            "{:width$}{}, // {}",
            "",
            value,
            comment,
            width = indent_depth + 4
        );
    }
    println!("{:width$}];", "", width = indent_depth);
}
<commit_msg>Add `crypt(3)` character set tables<commit_after>use std::collections::HashMap;
use std::iter::Iterator;

fn main() {
    println!("pub const INVALID_VALUE: u8 = 255;");

    // A-Z
    let standard_alphabet: Vec<u8> = (0x41..0x5B)
        // a-z
        .chain(0x61..0x7B)
        // 0-9
        .chain(0x30..0x3A)
        // +
        .chain(0x2B..0x2C)
        // /
        .chain(0x2F..0x30)
        .collect();
    print_encode_table(&standard_alphabet, "STANDARD_ENCODE", 0);
    print_decode_table(&standard_alphabet, "STANDARD_DECODE", 0);

    // A-Z
    let url_alphabet: Vec<u8> = (0x41..0x5B)
        // a-z
        .chain(0x61..0x7B)
        // 0-9
        .chain(0x30..0x3A)
        // -
        .chain(0x2D..0x2E)
        // _s
        .chain(0x5F..0x60)
        .collect();
    print_encode_table(&url_alphabet, "URL_SAFE_ENCODE", 0);
    print_decode_table(&url_alphabet, "URL_SAFE_DECODE", 0);

    // ./0123456789
    let crypt_alphabet: Vec<u8> = (b'.'..(b'9'+1))
        // A-Z
        .chain(b'A'..(b'Z'+1))
        // a-z
        .chain(b'a'..(b'z'+1))
        .collect();
    print_encode_table(&crypt_alphabet, "CRYPT_ENCODE", 0);
    print_decode_table(&crypt_alphabet, "CRYPT_DECODE", 0);
}

fn print_encode_table(alphabet: &[u8], const_name: &str, indent_depth: usize) {
    println!("#[cfg_attr(rustfmt, rustfmt_skip)]");
    println!(
        "{:width$}pub const {}: &'static [u8; 64] = &[",
        "",
        const_name,
        width = indent_depth
    );

    for (i, b) in alphabet.iter().enumerate() {
        println!(
            "{:width$}{}, // input {} (0x{:X}) => '{}' (0x{:X})",
            "",
            b,
            i,
            i,
            String::from_utf8(vec![*b as u8]).unwrap(),
            b,
            width = indent_depth + 4
        );
    }

    println!("{:width$}];", "", width = indent_depth);
}

fn print_decode_table(alphabet: &[u8], const_name: &str, indent_depth: usize) {
    // map of alphabet bytes to 6-bit morsels
    let mut input_to_morsel = HashMap::<u8, u8>::new();

    // standard base64 alphabet bytes, in order
    for (morsel, ascii_byte) in alphabet.iter().enumerate() {
        // truncation cast is fine here
        let _ = input_to_morsel.insert(*ascii_byte, morsel as u8);
    }

    println!("#[cfg_attr(rustfmt, rustfmt_skip)]");
    println!(
        "{:width$}pub const {}: &'static [u8; 256] = &[",
        "",
        const_name,
        width = indent_depth
    );
    for ascii_byte in 0..256 {
        let (value, comment) = match input_to_morsel.get(&(ascii_byte as u8)) {
            None => (
                "INVALID_VALUE".to_string(),
                format!("input {} (0x{:X})", ascii_byte, ascii_byte),
            ),
            Some(v) => (
                format!("{}", *v),
                format!(
                    "input {} (0x{:X} char '{}') => {} (0x{:X})",
                    ascii_byte,
                    ascii_byte,
                    String::from_utf8(vec![ascii_byte as u8]).unwrap(),
                    *v,
                    *v
                ),
            ),
        };

        println!(
            "{:width$}{}, // {}",
            "",
            value,
            comment,
            width = indent_depth + 4
        );
    }
    println!("{:width$}];", "", width = indent_depth);
}
<|endoftext|>


<commit_before>use std::process;

use utils::screen::Screen;
use utils::screen::ScreenStatus;
use aws::awsController;

const header: &'static str = r###"
   -----------------------------------------

   ██████╗  █████╗ ██╗    ██╗███████╗████████╗
   ██╔══██╗██╔══██╗██║    ██║██╔════╝╚══██╔══╝
   ██████╔╝███████║██║ █╗ ██║███████╗   ██║
   ██╔══██╗██╔══██║██║███╗██║╚════██║   ██║
   ██║  ██║██║  ██║╚███╔███╔╝███████║   ██║
   ╚═╝  ╚═╝╚═╝  ╚═╝ ╚══╝╚══╝ ╚══════╝   ╚═╝

   ------------------------------------------

   rawst is the interactive tool for AWS CLI written in Rust.

   "###;

pub struct topController {
    screen: Screen,
}

impl topController {

    pub fn new() -> topController {
        topController {
            screen: Screen::new(),
        }
    }

    pub fn run(&mut self) {

        self.screen.header = header;
        self.screen.lines  = vec!["aws".to_string(), "q".to_string()];

        match self.screen.select_line() {
            ScreenStatus::Error | ScreenStatus::Quit => println!("error"),
            ScreenStatus::Selected(ref c) if c == "a" => self.aws(),
            _ => process::exit(0),
        }
    }

    fn aws(&self) {
        let mut aws = awsController::new();
        aws.run();
    }
}
<commit_msg>Fix str type<commit_after>use std::process;

use utils::screen::Screen;
use utils::screen::ScreenStatus;
use aws::awsController;

const header: &'static str = r###"
   -----------------------------------------

   ██████╗  █████╗ ██╗    ██╗███████╗████████╗
   ██╔══██╗██╔══██╗██║    ██║██╔════╝╚══██╔══╝
   ██████╔╝███████║██║ █╗ ██║███████╗   ██║
   ██╔══██╗██╔══██║██║███╗██║╚════██║   ██║
   ██║  ██║██║  ██║╚███╔███╔╝███████║   ██║
   ╚═╝  ╚═╝╚═╝  ╚═╝ ╚══╝╚══╝ ╚══════╝   ╚═╝

   ------------------------------------------

   rawst is the interactive tool for AWS CLI written in Rust.

   "###;

pub struct topController {
    screen: Screen,
}

impl topController {

    pub fn new() -> topController {
        topController {
            screen: Screen::new(),
        }
    }

    pub fn run(&mut self) {

        self.screen.header = header.to_string();
        self.screen.lines  = vec!["aws".to_string(), "q".to_string()];

        match self.screen.select_line() {
            ScreenStatus::Error | ScreenStatus::Quit => println!("error"),
            ScreenStatus::Selected(ref c) if c == "a" => self.aws(),
            _ => process::exit(0),
        }
    }

    fn aws(&self) {
        let mut aws = awsController::new();
        aws.run();
    }
}
<|endoftext|>