<commit_before>use std::fs::File;
use std::path::Path;
use std::io::prelude::*;
use std::sync::RwLock;
use std::error::Error;

use iron::prelude::*;
use iron::{status};
use iron::{AfterMiddleware, typemap};
use iron::modifier::Modifier;
use plugin::Plugin as PluginFor;
use iron::headers::ContentType;
use walkdir::{WalkDir, DirEntry};

use handlebars::Handlebars;
use serialize::json::{ToJson, Json};

#[derive(Clone)]
pub struct Template {
    name: String,
    value: Json
}

impl Template {
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: name.to_string(),
            value: value.to_json()
        }
    }
}

pub struct HandlebarsEngine {
    pub prefix: String,
    pub suffix: String,
    pub registry: RwLock<Box<Handlebars>>
}

impl typemap::Key for HandlebarsEngine {
    type Value = Template;
}

impl Modifier<Response> for Template {
    fn modify(self, resp: &mut Response) {
        resp.extensions.insert::<HandlebarsEngine>(self);
    }
}

impl PluginFor<Response> for HandlebarsEngine {
    type Error = ();

    fn eval(resp: &mut Response) -> Result<Template, ()> {
        match resp.extensions.get::<HandlebarsEngine>(){
            Some(t) => Ok(t.clone()),
            None => Err(())
        }
    }
}

fn read_file(path: &Path) -> Option<String> {
    if let Ok(mut file) = File::open(path) {
        let mut buf = String::new();
        if file.read_to_string(&mut buf).is_ok() {
            Some(buf)
        } else {
            info!("Failed to read file {}, skipped", path.display());
            None
        }
    } else {
        info!("Failed to open file {}, skipped.", path.display());
        None
    }
}

fn is_hidden_or_temp(entry: &DirEntry, suffix: &str) -> bool {
    entry.file_name().to_str()
        .and_then(|s| Some(s.starts_with(".") || s.starts_with("#") || s.ends_with(suffix)))
        .unwrap_or(false)
}

impl HandlebarsEngine {
    pub fn reload(&self) {
        let mut hbs = self.registry.write().unwrap();

        let mut prefix = self.prefix.clone();
        if !prefix.ends_with('/') {
            prefix.push('/');
        }
        let normalized_prefix = prefix;

        let prefix_path = Path::new(&normalized_prefix);
        let walker = WalkDir::new(prefix_path);

        hbs.clear_templates();
        let suffix = &self.suffix;
        for p in walker.into_iter().filter(|e| e.is_ok() && !is_hidden_or_temp(e.as_ref().unwrap(), suffix)).map(|e| e.unwrap()) {
            let path = p.path();
            let disp = path.to_str().unwrap();
            let tpl_name = &disp[normalized_prefix.len() .. disp.len()-suffix.len()];
            if let Some(tpl) = read_file(&path) {
                if let Err(e) = hbs.register_template_string(tpl_name, tpl){
                    warn!("Failed to parse template {}, {}", tpl_name, e);
                }
            }
        }
    }

    pub fn from(prefix: &str, suffix: &str, custom: Handlebars) -> HandlebarsEngine {
        let eng = HandlebarsEngine {
            prefix: prefix.to_string(),
            suffix: suffix.to_string(),
            registry: RwLock::new(Box::new(custom))
        };
        eng.reload();
        eng
    }

    pub fn new(prefix: &str, suffix: &str) -> HandlebarsEngine {
        HandlebarsEngine::from(prefix,suffix, Handlebars::new())
    }
}

impl AfterMiddleware for HandlebarsEngine {
    fn after(&self, _: &mut Request, r: Response) -> IronResult<Response> {
        let mut resp = r;
        let page_wrapper = resp.extensions.get::<HandlebarsEngine>().as_ref()
            .and_then(|h| {
                let hbs = self.registry.read().unwrap();
                Some(hbs.render(&h.name, &h.value))
            });

        match page_wrapper {
            Some(page_result) => {
                match page_result {
                    Ok(page) => {
                        if !resp.headers.has::<ContentType>() {
                            resp.headers.set(ContentType::html());
                        }
                        resp.set_mut(page);
                        Ok(resp)
                    }
                    Err(e) => {
                        info!("{}", e.description());
                        Err(IronError::new(e, status::InternalServerError))
                    }
                }
            }
            None => {
                Ok(resp)
            }
        }
    }
}

#[cfg(test)]
mod test {
    use serialize::json::ToJson;
    use std::collections::BTreeMap;
    use iron::prelude::*;
    use middleware::*;
    use handlebars::{Handlebars, RenderError, RenderContext, Helper, Context};

    fn hello_world() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_string(), "Handlebars on Iron".to_json());

        Ok(resp.set(Template::new("index", data)))
    }

    #[test]
    fn test_resp_set() {
        let mut resp = hello_world().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.name, "index".to_string());
                assert_eq!(h.value.as_object().unwrap()
                           .get(&"title".to_string()).unwrap()
                           .as_string().unwrap(),
                           "Handlebars on Iron");
            },
            _ => panic!("template expected")
        }
    }

    #[test]
    fn test_register_helper() {
        let hbs = HandlebarsEngine::new("./examples/templates", ".hbs");
        let mut reg = hbs.registry.write().unwrap();
        reg.register_helper("ignore", Box::new(|_: &Context, _: &Helper, _: &Handlebars, _: &mut RenderContext| -> Result<(), RenderError> {
            Ok(())
        }));
    }
}
<commit_msg>(fix) ignore top-most directory<commit_after>use std::fs::File;
use std::path::Path;
use std::io::prelude::*;
use std::sync::RwLock;
use std::error::Error;

use iron::prelude::*;
use iron::{status};
use iron::{AfterMiddleware, typemap};
use iron::modifier::Modifier;
use plugin::Plugin as PluginFor;
use iron::headers::ContentType;
use walkdir::{WalkDir, DirEntry};

use handlebars::Handlebars;
use serialize::json::{ToJson, Json};

#[derive(Clone)]
pub struct Template {
    name: String,
    value: Json
}

impl Template {
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: name.to_string(),
            value: value.to_json()
        }
    }
}

pub struct HandlebarsEngine {
    pub prefix: String,
    pub suffix: String,
    pub registry: RwLock<Box<Handlebars>>
}

impl typemap::Key for HandlebarsEngine {
    type Value = Template;
}

impl Modifier<Response> for Template {
    fn modify(self, resp: &mut Response) {
        resp.extensions.insert::<HandlebarsEngine>(self);
    }
}

impl PluginFor<Response> for HandlebarsEngine {
    type Error = ();

    fn eval(resp: &mut Response) -> Result<Template, ()> {
        match resp.extensions.get::<HandlebarsEngine>(){
            Some(t) => Ok(t.clone()),
            None => Err(())
        }
    }
}

fn read_file(path: &Path) -> Option<String> {
    if let Ok(mut file) = File::open(path) {
        let mut buf = String::new();
        if file.read_to_string(&mut buf).is_ok() {
            Some(buf)
        } else {
            info!("Failed to read file {}, skipped", path.display());
            None
        }
    } else {
        info!("Failed to open file {}, skipped.", path.display());
        None
    }
}

fn is_hidden_or_temp(entry: &DirEntry, suffix: &str) -> bool {
    entry.file_name().to_str()
        .and_then(|s| Some(s.starts_with(".") || s.starts_with("#") || s.ends_with(suffix)))
        .unwrap_or(false)
}

impl HandlebarsEngine {
    pub fn reload(&self) {
        let mut hbs = self.registry.write().unwrap();

        let mut prefix = self.prefix.clone();
        if !prefix.ends_with('/') {
            prefix.push('/');
        }
        let normalized_prefix = prefix;

        let prefix_path = Path::new(&normalized_prefix);
        let walker = WalkDir::new(prefix_path);

        hbs.clear_templates();
        let suffix = &self.suffix;
        for p in walker.min_depth(1).into_iter().filter(|e| e.is_ok() && !is_hidden_or_temp(e.as_ref().unwrap(), suffix)).map(|e| e.unwrap()) {
            let path = p.path();
            let disp = path.to_str().unwrap();
            let tpl_name = &disp[normalized_prefix.len() .. disp.len()-suffix.len()];
            if let Some(tpl) = read_file(&path) {
                if let Err(e) = hbs.register_template_string(tpl_name, tpl){
                    warn!("Failed to parse template {}, {}", tpl_name, e);
                }
            }
        }
    }

    pub fn from(prefix: &str, suffix: &str, custom: Handlebars) -> HandlebarsEngine {
        let eng = HandlebarsEngine {
            prefix: prefix.to_string(),
            suffix: suffix.to_string(),
            registry: RwLock::new(Box::new(custom))
        };
        eng.reload();
        eng
    }

    pub fn new(prefix: &str, suffix: &str) -> HandlebarsEngine {
        HandlebarsEngine::from(prefix, suffix, Handlebars::new())
    }
}

impl AfterMiddleware for HandlebarsEngine {
    fn after(&self, _: &mut Request, r: Response) -> IronResult<Response> {
        let mut resp = r;
        let page_wrapper = resp.extensions.get::<HandlebarsEngine>().as_ref()
            .and_then(|h| {
                let hbs = self.registry.read().unwrap();
                Some(hbs.render(&h.name, &h.value))
            });

        match page_wrapper {
            Some(page_result) => {
                match page_result {
                    Ok(page) => {
                        if !resp.headers.has::<ContentType>() {
                            resp.headers.set(ContentType::html());
                        }
                        resp.set_mut(page);
                        Ok(resp)
                    }
                    Err(e) => {
                        info!("{}", e.description());
                        Err(IronError::new(e, status::InternalServerError))
                    }
                }
            }
            None => {
                Ok(resp)
            }
        }
    }
}

#[cfg(test)]
mod test {
    use serialize::json::ToJson;
    use std::collections::BTreeMap;
    use iron::prelude::*;
    use middleware::*;
    use handlebars::{Handlebars, RenderError, RenderContext, Helper, Context};

    fn hello_world() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_string(), "Handlebars on Iron".to_json());

        Ok(resp.set(Template::new("index", data)))
    }

    #[test]
    fn test_resp_set() {
        let mut resp = hello_world().ok().expect("response expected");

        // use response plugin to retrieve a cloned template for testing
        match resp.get::<HandlebarsEngine>() {
            Ok(h) => {
                assert_eq!(h.name, "index".to_string());
                assert_eq!(h.value.as_object().unwrap()
                           .get(&"title".to_string()).unwrap()
                           .as_string().unwrap(),
                           "Handlebars on Iron");
            },
            _ => panic!("template expected")
        }
    }

    #[test]
    fn test_register_helper() {
        let hbs = HandlebarsEngine::new("./examples/templates", ".hbs");
        let mut reg = hbs.registry.write().unwrap();
        reg.register_helper("ignore", Box::new(|_: &Context, _: &Helper, _: &Handlebars, _: &mut RenderContext| -> Result<(), RenderError> {
            Ok(())
        }));
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use rustc_serialize::json::{ToJson, Json};

#[derive(Debug, Clone)]
pub struct Feed {
    pub id:           String,
    pub subscribers:  Option<i64>,
    pub title:        Option<String>,
    pub description:  Option<String>,
    pub language:     Option<String>,
    pub velocity:     Option<f64>,
    pub website:      Option<String>,
    pub topics:       Option<Vec<String>>,
    pub status:       Option<String>,
    pub curated:      Option<bool>,
    pub featured:     Option<bool>,
    pub last_updated: Option<i64>,

    pub visual_url:   Option<String>,
    pub icon_url:     Option<String>,
    pub cover_url:    Option<String>,
}

impl ToJson for Feed {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("id".to_string()          , self.id.to_string().to_json());
        d.insert("subscribers".to_string() , self.subscribers.to_json());
        d.insert("title".to_string()       , self.title.to_json());
        d.insert("description".to_string() , self.description.to_json());
        d.insert("language".to_string()    , self.language.to_json());
        d.insert("velocity".to_string()    , self.velocity.to_json());
        d.insert("website".to_string()     , self.website.to_json());
        d.insert("topics".to_string()      , self.topics.to_json());
        d.insert("status".to_string()      , self.status.to_json());
        d.insert("curated".to_string()     , self.curated.to_json());
        d.insert("featured".to_string()    , self.featured.to_json());
        d.insert("last_updated".to_string(), self.last_updated.to_json());
        d.insert("visual_url".to_string()  , self.visual_url.to_json());
        d.insert("icon_url".to_string()    , self.icon_url.to_json());
        d.insert("cover_url".to_string()   , self.cover_url.to_json());
        Json::Object(d)
    }
}
<commit_msg>feed.rs<commit_after>use std::collections::BTreeMap;
use rustc_serialize::json::{ToJson, Json};
use error::Error;
use super::conn;

#[derive(Debug, Clone)]
pub struct Feed {
    pub id:           String,
    pub subscribers:  Option<i64>,
    pub title:        Option<String>,
    pub description:  Option<String>,
    pub language:     Option<String>,
    pub velocity:     Option<f64>,
    pub website:      Option<String>,
    pub topics:       Option<Vec<String>>,
    pub status:       Option<String>,
    pub curated:      Option<bool>,
    pub featured:     Option<bool>,
    pub last_updated: Option<i64>,

    pub visual_url:   Option<String>,
    pub icon_url:     Option<String>,
    pub cover_url:    Option<String>,
}

impl ToJson for Feed {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("id".to_string()          , self.id.to_string().to_json());
        d.insert("subscribers".to_string() , self.subscribers.to_json());
        d.insert("title".to_string()       , self.title.to_json());
        d.insert("description".to_string() , self.description.to_json());
        d.insert("language".to_string()    , self.language.to_json());
        d.insert("velocity".to_string()    , self.velocity.to_json());
        d.insert("website".to_string()     , self.website.to_json());
        d.insert("topics".to_string()      , self.topics.to_json());
        d.insert("status".to_string()      , self.status.to_json());
        d.insert("curated".to_string()     , self.curated.to_json());
        d.insert("featured".to_string()    , self.featured.to_json());
        d.insert("last_updated".to_string(), self.last_updated.to_json());
        d.insert("visual_url".to_string()  , self.visual_url.to_json());
        d.insert("icon_url".to_string()    , self.icon_url.to_json());
        d.insert("cover_url".to_string()   , self.cover_url.to_json());
        Json::Object(d)
    }
}

impl Feed {
    pub fn find_by_id(id: String) -> Result<Feed, Error> {
        let conn = conn().unwrap();
        let stmt = conn.prepare("SELECT id, subscribers, title, description, language, velocity, website, status, curated, featured, last_updated, visual_url, icon_url, cover_url FROM feeds WHERE id = $1").unwrap();
        for row in stmt.query(&[&id]).unwrap().iter() {
            return Ok(Feed {
                    id: row.get(0),
           subscribers: row.get(1),
                 title: row.get(2),
           description: row.get(3),
              language: row.get(4),
              velocity: row.get(5),
               website: row.get(6),
                topics: None,
                status: row.get(7),
               curated: row.get(8),
              featured: row.get(9),
          last_updated: row.get(10),
            visual_url: row.get(11),
              icon_url: row.get(12),
             cover_url: row.get(13),
            });
        }
        return Err(Error::NotFound)
    }

    pub fn find_all() -> Vec<Feed> {
        let conn = conn().unwrap();
        let stmt = conn.prepare("SELECT id, subscribers, title, description, language, velocity, website, status, curated, featured, last_updated, visual_url, icon_url, cover_url FROM feeds").unwrap();
        let mut feeds = Vec::new();
        for row in stmt.query(&[]).unwrap().iter() {
            feeds.push(Feed {
                    id: row.get(0),
           subscribers: row.get(1),
                 title: row.get(2),
           description: row.get(3),
              language: row.get(4),
              velocity: row.get(5),
               website: row.get(6),
                topics: None,
                status: row.get(7),
               curated: row.get(8),
              featured: row.get(9),
          last_updated: row.get(10),
            visual_url: row.get(11),
              icon_url: row.get(12),
             cover_url: row.get(13),
            })
        }
        return feeds
    }

    pub fn create(feed: Feed) -> Result<(), Error> {
        let conn = conn().unwrap();
        let stmt = conn.prepare("INSERT INTO feeds (id, u) VALUES ($1)").unwrap();
        let _ = try!(stmt.query(&[
            &feed.id,
            &feed.subscribers,
            &feed.title,
            &feed.description,
            &feed.language,
            &feed.velocity,
            &feed.website,
            &feed.topics,
            &feed.status,
            &feed.curated,
            &feed.featured,
            &feed.last_updated,
            &feed.visual_url,
            &feed.icon_url,
            &feed.cover_url,
        ]));
        Ok(())
    }
}
<|endoftext|>


<commit_before>use core;

use core::hash::Hasher;
use number_streams::NumberStreams;

const CHUNK_SIZE: usize = 16;

const PRIME_1: u32 = 2654435761;
const PRIME_2: u32 = 2246822519;
const PRIME_3: u32 = 3266489917;
const PRIME_4: u32 =  668265263;
const PRIME_5: u32 =  374761393;

#[derive(Copy,Clone,PartialEq)]
struct XxCore {
    v1: u32,
    v2: u32,
    v3: u32,
    v4: u32,
}

/// Calculates the 32-bit hash. Care should be taken when using this
/// hash.
///
/// Although this struct implements `Hasher`, it only calculates a
/// 32-bit number, leaving the upper bits as 0. This means it is
/// unlikely to be correct to use this in places like a `HashMap`.
#[derive(Debug,Copy,Clone)]
pub struct XxHash {
    total_len: u32,
    seed: u32,
    core: XxCore,
    buffer: [u8; CHUNK_SIZE],
    buffer_usage: usize,
}

impl XxCore {
    fn with_seed(seed: u32) -> XxCore {
        XxCore {
            v1: seed.wrapping_add(PRIME_1).wrapping_add(PRIME_2),
            v2: seed.wrapping_add(PRIME_2),
            v3: seed,
            v4: seed.wrapping_sub(PRIME_1),
        }
    }

    #[inline(always)]
    fn ingest_chunks<I>(&mut self, values: I)
        where I: Iterator<Item=u32>
    {
        #[inline(always)]
        fn ingest_one_number(mut current_value: u32, mut value: u32) -> u32 {
            value = value.wrapping_mul(PRIME_2);
            current_value = current_value.wrapping_add(value);
            current_value = current_value.rotate_left(13); // DIFF
            current_value.wrapping_mul(PRIME_1)
        };

        // By drawing these out, we can avoid going back and forth to
        // memory. It only really helps for large files, when we need
        // to iterate multiple times here.

        let mut v1 = self.v1;
        let mut v2 = self.v2;
        let mut v3 = self.v3;
        let mut v4 = self.v4;

        let mut values = values.peekable();

        while values.peek().is_some() {
            v1 = ingest_one_number(v1, values.next().unwrap());
            v2 = ingest_one_number(v2, values.next().unwrap());
            v3 = ingest_one_number(v3, values.next().unwrap());
            v4 = ingest_one_number(v4, values.next().unwrap());
        }

        self.v1 = v1;
        self.v2 = v2;
        self.v3 = v3;
        self.v4 = v4;
    }

    #[inline(always)]
    fn finish(&self) -> u32 {
        // The original code pulls out local vars for v[1234]
        // here. Performance tests did not show that to be effective
        // here, presumably because this method is not called in a
        // tight loop.

        let mut hash;

        hash =                   self.v1.rotate_left( 1);
        hash = hash.wrapping_add(self.v2.rotate_left( 7));
        hash = hash.wrapping_add(self.v3.rotate_left(12));
        hash = hash.wrapping_add(self.v4.rotate_left(18));

        hash
    }
}

impl core::fmt::Debug for XxCore {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
        write!(
            f, "XxCore {{ {:016x} {:016x} {:016x} {:016x} }}",
            self.v1, self.v2, self.v3, self.v4
        )
    }
}

impl XxHash {
    /// Constructs the hash with an initial seed
    pub fn with_seed(seed: u32) -> XxHash {
        XxHash {
            total_len: 0,
            seed: seed,
            core: XxCore::with_seed(seed),
            buffer: unsafe { ::core::mem::uninitialized() },
            buffer_usage: 0,
        }
    }
}

impl Default for XxHash {
    fn default() -> XxHash {
        XxHash::with_seed(0)
    }
}

impl Hasher for XxHash {
    fn write(&mut self, bytes: &[u8]) {
        let mut bytes = bytes;

        self.total_len += bytes.len() as u32;

        // Even with new data, we still don't have a full buffer. Wait
        // until we have a full buffer.
        if self.buffer_usage + bytes.len() < self.buffer.len() {
            unsafe {
                let tail = self.buffer.as_mut_ptr().offset(self.buffer_usage as isize);
                core::ptr::copy_nonoverlapping(bytes.as_ptr(), tail, bytes.len());
            }
            self.buffer_usage += bytes.len();
            return;
        }

        // Some data left from previous update. Fill the buffer and
        // consume it first.
        if self.buffer_usage > 0 {
            let bytes_to_use = self.buffer.len() - self.buffer_usage;
            let (to_use, leftover) = bytes.split_at(bytes_to_use);

            unsafe {
                let tail = self.buffer.as_mut_ptr().offset(self.buffer_usage as isize);
                core::ptr::copy_nonoverlapping(to_use.as_ptr(), tail, bytes_to_use);
            }

            let (iter, _) = self.buffer.u32_stream();

            self.core.ingest_chunks(iter);

            bytes = leftover;
            self.buffer_usage = 0;
        }

        // Consume the input data in large chunks
        let (iter, bytes) = bytes.u32_stream_with_stride(4);
        self.core.ingest_chunks(iter);

        // Save any leftover data for the next call
        if bytes.len() > 0 {
            unsafe {
                core::ptr::copy_nonoverlapping(bytes.as_ptr(), self.buffer.as_mut_ptr(), bytes.len());
            }
            self.buffer_usage = bytes.len();
        }
    }

    fn finish(&self) -> u64 { // NODIFF
        let mut hash;

        // We have processed at least one full chunk
        if self.total_len >= CHUNK_SIZE as u32 {
            hash = self.core.finish();
        } else {
            hash = self.seed.wrapping_add(PRIME_5);
        }

        hash = hash.wrapping_add(self.total_len);

        let buffered = &self.buffer[..self.buffer_usage];
        let (buffered_u32s, buffered) = buffered.u32_stream();

        for k1 in buffered_u32s {
            let k1 = k1.wrapping_mul(PRIME_3);
            hash = hash.wrapping_add(k1);
            hash = hash.rotate_left(17);
            hash = hash.wrapping_mul(PRIME_4);
        }

        for buffered_u8 in buffered {
            let k1 = (*buffered_u8 as u32).wrapping_mul(PRIME_5);
            hash = hash.wrapping_add(k1);
            hash = hash.rotate_left(11);
            hash = hash.wrapping_mul(PRIME_1);
        }

        // The final intermixing
        hash ^= hash >> 15;
        hash = hash.wrapping_mul(PRIME_2);
        hash ^= hash >> 13;
        hash = hash.wrapping_mul(PRIME_3);
        hash ^= hash >> 16;

        hash as u64
    }
}

#[cfg(feature = "std")]
pub use ::std_support::thirty_two::RandomXxHashBuilder;

#[cfg(test)]
mod test {
    use std::prelude::v1::*;
    use std::hash::{Hasher, BuildHasherDefault};
    use std::collections::HashMap;
    use super::{XxHash, RandomXxHashBuilder};

    #[test]
    fn ingesting_byte_by_byte_is_equivalent_to_large_chunks() {
        let bytes: Vec<_> = (0..32).map(|_| 0).collect();

        let mut byte_by_byte = XxHash::with_seed(0);
        for byte in bytes.chunks(1) {
            byte_by_byte.write(byte);
        }

        let mut one_chunk = XxHash::with_seed(0);
        one_chunk.write(&bytes);

        assert_eq!(byte_by_byte.core, one_chunk.core);
    }

    #[test]
    fn hash_of_nothing_matches_c_implementation() {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(&[]);
        assert_eq!(hasher.finish(), 0x02cc5d05);
    }

    #[test]
    fn hash_of_single_byte_matches_c_implementation() {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(&[42]);
        assert_eq!(hasher.finish(), 0xe0fe705f);
    }

    #[test]
    fn hash_of_multiple_bytes_matches_c_implementation() {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(b"Hello, world!\0");
        assert_eq!(hasher.finish(), 0x9e5e7e93);
    }

    #[test]
    fn hash_of_multiple_chunks_matches_c_implementation() {
        let bytes: Vec<_> = (0..100).collect();
        let mut hasher = XxHash::with_seed(0);
        hasher.write(&bytes);
        assert_eq!(hasher.finish(), 0x7f89ba44);
    }

    #[test]
    fn hash_with_different_seed_matches_c_implementation() {
        let mut hasher = XxHash::with_seed(0x42c91977);
        hasher.write(&[]);
        assert_eq!(hasher.finish(), 0xd6bf8459);
    }

    #[test]
    fn hash_with_different_seed_and_multiple_chunks_matches_c_implementation() {
        let bytes: Vec<_> = (0..100).collect();
        let mut hasher = XxHash::with_seed(0x42c91977);
        hasher.write(&bytes);
        assert_eq!(hasher.finish(), 0x6d2f6c17);
    }

    #[test]
    fn can_be_used_in_a_hashmap_with_a_default_seed() {
        let mut hash: HashMap<_, _, BuildHasherDefault<XxHash>> = Default::default();
        hash.insert(42, "the answer");
        assert_eq!(hash.get(&42), Some(&"the answer"));
    }

    #[test]
    fn can_be_used_in_a_hashmap_with_a_random_seed() {
        let mut hash: HashMap<_, _, RandomXxHashBuilder> = Default::default();
        hash.insert(42, "the answer");
        assert_eq!(hash.get(&42), Some(&"the answer"));
    }
}
<commit_msg>Add serialization capabilities for XxHash32<commit_after>use core;

use core::hash::Hasher;
use number_streams::NumberStreams;

#[cfg(feature="serialize")]
use serde::{Serialize, Deserialize};

const CHUNK_SIZE: usize = 16;

const PRIME_1: u32 = 2654435761;
const PRIME_2: u32 = 2246822519;
const PRIME_3: u32 = 3266489917;
const PRIME_4: u32 =  668265263;
const PRIME_5: u32 =  374761393;

#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
#[derive(Copy,Clone,PartialEq)]
struct XxCore {
    v1: u32,
    v2: u32,
    v3: u32,
    v4: u32,
}

/// Calculates the 32-bit hash. Care should be taken when using this
/// hash.
///
/// Although this struct implements `Hasher`, it only calculates a
/// 32-bit number, leaving the upper bits as 0. This means it is
/// unlikely to be correct to use this in places like a `HashMap`.
#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
#[derive(Debug,Copy,Clone,PartialEq)]
pub struct XxHash {
    total_len: u32,
    seed: u32,
    core: XxCore,
    buffer: [u8; CHUNK_SIZE],
    buffer_usage: usize,
}

impl XxCore {
    fn with_seed(seed: u32) -> XxCore {
        XxCore {
            v1: seed.wrapping_add(PRIME_1).wrapping_add(PRIME_2),
            v2: seed.wrapping_add(PRIME_2),
            v3: seed,
            v4: seed.wrapping_sub(PRIME_1),
        }
    }

    #[inline(always)]
    fn ingest_chunks<I>(&mut self, values: I)
        where I: Iterator<Item=u32>
    {
        #[inline(always)]
        fn ingest_one_number(mut current_value: u32, mut value: u32) -> u32 {
            value = value.wrapping_mul(PRIME_2);
            current_value = current_value.wrapping_add(value);
            current_value = current_value.rotate_left(13); // DIFF
            current_value.wrapping_mul(PRIME_1)
        };

        // By drawing these out, we can avoid going back and forth to
        // memory. It only really helps for large files, when we need
        // to iterate multiple times here.

        let mut v1 = self.v1;
        let mut v2 = self.v2;
        let mut v3 = self.v3;
        let mut v4 = self.v4;

        let mut values = values.peekable();

        while values.peek().is_some() {
            v1 = ingest_one_number(v1, values.next().unwrap());
            v2 = ingest_one_number(v2, values.next().unwrap());
            v3 = ingest_one_number(v3, values.next().unwrap());
            v4 = ingest_one_number(v4, values.next().unwrap());
        }

        self.v1 = v1;
        self.v2 = v2;
        self.v3 = v3;
        self.v4 = v4;
    }

    #[inline(always)]
    fn finish(&self) -> u32 {
        // The original code pulls out local vars for v[1234]
        // here. Performance tests did not show that to be effective
        // here, presumably because this method is not called in a
        // tight loop.

        let mut hash;

        hash =                   self.v1.rotate_left( 1);
        hash = hash.wrapping_add(self.v2.rotate_left( 7));
        hash = hash.wrapping_add(self.v3.rotate_left(12));
        hash = hash.wrapping_add(self.v4.rotate_left(18));

        hash
    }
}

impl core::fmt::Debug for XxCore {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
        write!(
            f, "XxCore {{ {:016x} {:016x} {:016x} {:016x} }}",
            self.v1, self.v2, self.v3, self.v4
        )
    }
}

impl XxHash {
    /// Constructs the hash with an initial seed
    pub fn with_seed(seed: u32) -> XxHash {
        XxHash {
            total_len: 0,
            seed: seed,
            core: XxCore::with_seed(seed),
            buffer: [0; CHUNK_SIZE],
            buffer_usage: 0,
        }
    }
}

impl Default for XxHash {
    fn default() -> XxHash {
        XxHash::with_seed(0)
    }
}

impl Hasher for XxHash {
    fn write(&mut self, bytes: &[u8]) {
        let mut bytes = bytes;

        self.total_len += bytes.len() as u32;

        // Even with new data, we still don't have a full buffer. Wait
        // until we have a full buffer.
        if self.buffer_usage + bytes.len() < self.buffer.len() {
            unsafe {
                let tail = self.buffer.as_mut_ptr().offset(self.buffer_usage as isize);
                core::ptr::copy_nonoverlapping(bytes.as_ptr(), tail, bytes.len());
            }
            self.buffer_usage += bytes.len();
            return;
        }

        // Some data left from previous update. Fill the buffer and
        // consume it first.
        if self.buffer_usage > 0 {
            let bytes_to_use = self.buffer.len() - self.buffer_usage;
            let (to_use, leftover) = bytes.split_at(bytes_to_use);

            unsafe {
                let tail = self.buffer.as_mut_ptr().offset(self.buffer_usage as isize);
                core::ptr::copy_nonoverlapping(to_use.as_ptr(), tail, bytes_to_use);
            }

            let (iter, _) = self.buffer.u32_stream();

            self.core.ingest_chunks(iter);

            bytes = leftover;
            self.buffer_usage = 0;
        }

        // Consume the input data in large chunks
        let (iter, bytes) = bytes.u32_stream_with_stride(4);
        self.core.ingest_chunks(iter);

        // Save any leftover data for the next call
        if bytes.len() > 0 {
            unsafe {
                core::ptr::copy_nonoverlapping(bytes.as_ptr(), self.buffer.as_mut_ptr(), bytes.len());
            }
            self.buffer_usage = bytes.len();
        }
    }

    fn finish(&self) -> u64 { // NODIFF
        let mut hash;

        // We have processed at least one full chunk
        if self.total_len >= CHUNK_SIZE as u32 {
            hash = self.core.finish();
        } else {
            hash = self.seed.wrapping_add(PRIME_5);
        }

        hash = hash.wrapping_add(self.total_len);

        let buffered = &self.buffer[..self.buffer_usage];
        let (buffered_u32s, buffered) = buffered.u32_stream();

        for k1 in buffered_u32s {
            let k1 = k1.wrapping_mul(PRIME_3);
            hash = hash.wrapping_add(k1);
            hash = hash.rotate_left(17);
            hash = hash.wrapping_mul(PRIME_4);
        }

        for buffered_u8 in buffered {
            let k1 = (*buffered_u8 as u32).wrapping_mul(PRIME_5);
            hash = hash.wrapping_add(k1);
            hash = hash.rotate_left(11);
            hash = hash.wrapping_mul(PRIME_1);
        }

        // The final intermixing
        hash ^= hash >> 15;
        hash = hash.wrapping_mul(PRIME_2);
        hash ^= hash >> 13;
        hash = hash.wrapping_mul(PRIME_3);
        hash ^= hash >> 16;

        hash as u64
    }
}

#[cfg(feature = "std")]
pub use ::std_support::thirty_two::RandomXxHashBuilder;

#[cfg(test)]
mod test {
    use std::prelude::v1::*;
    use std::hash::{Hasher, BuildHasherDefault};
    use std::collections::HashMap;
    use super::{XxHash, RandomXxHashBuilder};

    #[test]
    fn ingesting_byte_by_byte_is_equivalent_to_large_chunks() {
        let bytes: Vec<_> = (0..32).map(|_| 0).collect();

        let mut byte_by_byte = XxHash::with_seed(0);
        for byte in bytes.chunks(1) {
            byte_by_byte.write(byte);
        }

        let mut one_chunk = XxHash::with_seed(0);
        one_chunk.write(&bytes);

        assert_eq!(byte_by_byte.core, one_chunk.core);
    }

    #[test]
    fn hash_of_nothing_matches_c_implementation() {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(&[]);
        assert_eq!(hasher.finish(), 0x02cc5d05);
    }

    #[test]
    fn hash_of_single_byte_matches_c_implementation() {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(&[42]);
        assert_eq!(hasher.finish(), 0xe0fe705f);
    }

    #[test]
    fn hash_of_multiple_bytes_matches_c_implementation() {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(b"Hello, world!\0");
        assert_eq!(hasher.finish(), 0x9e5e7e93);
    }

    #[test]
    fn hash_of_multiple_chunks_matches_c_implementation() {
        let bytes: Vec<_> = (0..100).collect();
        let mut hasher = XxHash::with_seed(0);
        hasher.write(&bytes);
        assert_eq!(hasher.finish(), 0x7f89ba44);
    }

    #[test]
    fn hash_with_different_seed_matches_c_implementation() {
        let mut hasher = XxHash::with_seed(0x42c91977);
        hasher.write(&[]);
        assert_eq!(hasher.finish(), 0xd6bf8459);
    }

    #[test]
    fn hash_with_different_seed_and_multiple_chunks_matches_c_implementation() {
        let bytes: Vec<_> = (0..100).collect();
        let mut hasher = XxHash::with_seed(0x42c91977);
        hasher.write(&bytes);
        assert_eq!(hasher.finish(), 0x6d2f6c17);
    }

    #[test]
    fn can_be_used_in_a_hashmap_with_a_default_seed() {
        let mut hash: HashMap<_, _, BuildHasherDefault<XxHash>> = Default::default();
        hash.insert(42, "the answer");
        assert_eq!(hash.get(&42), Some(&"the answer"));
    }

    #[test]
    fn can_be_used_in_a_hashmap_with_a_random_seed() {
        let mut hash: HashMap<_, _, RandomXxHashBuilder> = Default::default();
        hash.insert(42, "the answer");
        assert_eq!(hash.get(&42), Some(&"the answer"));
    }

    #[cfg(feature="serialize")]
    type TestResult<T = ()> = Result<T, Box<dyn std::error::Error>>;

    #[cfg(feature="serialize")]
    #[test]
    fn test_serialization_cycle() -> TestResult {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(b"Hello, world!\0");
        hasher.finish();

        let serialized = serde_json::to_string(&hasher)?;
        let unserialized: XxHash = serde_json::from_str(&serialized)?;
        assert_eq!(hasher, unserialized);
        Ok(())
    }

    #[cfg(feature="serialize")]
    #[test]
    fn test_serialization_stability() -> TestResult {
        let mut hasher = XxHash::with_seed(0);
        hasher.write(b"Hello, world!\0");
        hasher.finish();

        let serialized = r#"{
            "total_len": 14,
            "seed": 0,
            "core": {
              "v1": 606290984,
              "v2": 2246822519,
              "v3": 0,
              "v4": 1640531535
            },
            "buffer": [
              72,  101, 108, 108, 111, 44, 32, 119,
              111, 114, 108, 100, 33,  0,  0,  0
            ],
            "buffer_usage": 14
        }"#;

        let unserialized: XxHash = serde_json::from_str(serialized).unwrap();
        assert_eq!(hasher, unserialized);
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::iter::Iterator;
use parser::Parser;

pub use self::UserReply::{
   TakeFile,
   MoveToTrash,
   ShowDiff,
   ShowDiffWith,
   ShowDiffBetween,
   Skip,
   Quit,
   Help
};

pub type FileNum = uint;

#[deriving(Show, PartialEq, Eq)]
pub enum UserReply
{
   TakeFile(FileNum),
   MoveToTrash,
   ShowDiff,
   ShowDiffWith(FileNum),
   ShowDiffBetween(FileNum, FileNum),
   Skip,
   Quit,
   Help
}

pub fn parse(input: &String, num_conf_files: uint) -> Option<UserReply>
{
   if input.is_empty() || num_conf_files == 0 {
      return None;
   }

   let lowercase_input: String = input.chars()
                                      .map(|c| c.to_lowercase())
                                      .collect();

   let mut parser = Parser::new(lowercase_input.as_slice());
   parser.skip_whitespace();
   match parser.take_char() {
      Err(..) => None,

      Ok(c)   => {
         parser.skip_whitespace();
         let nothing_left = parser.eof();
         let uints = take_uints(&mut parser);
         match c {
            't' => {
               match uints.len() {
                  1 if valid_file_num(uints[0], num_conf_files)
                  => Some(TakeFile(uints[0])),

                  _ => None
               }
            }

            'd' => {
               match uints.len() {
                  0 if num_conf_files == 1
                  => Some(ShowDiff),

                  1 if valid_file_num(uints[0], num_conf_files)
                  => Some(ShowDiffWith(uints[0])),

                  2 if valid_file_num(uints[0], num_conf_files) && valid_file_num(uints[1], num_conf_files)
                  => Some(ShowDiffBetween(uints[0], uints[1])),

                  _ => None
               }
            }

            'm'      if nothing_left => Some(MoveToTrash),
            's'      if nothing_left => Some(Skip),
            'q'      if nothing_left => Some(Quit),
            'h' |'?' if nothing_left => Some(Help),

            _ => None,
         }
      }
   }
}

fn valid_file_num(file_num: uint, num_confs: uint) -> bool
{
   file_num > 0 && file_num <= num_confs
}

fn take_uints(parser: &mut Parser) -> Vec<uint>
{
   let mut uints  = Vec::new();
   while ! parser.eof() {
      parser.skip_whitespace();
      match parser.take_uint() {
         Ok(uint) => uints.push(uint),
         Err(..)  => break
      }
   }

   uints
}

#[test]
fn tests()
{
   test_str("t"       , None);
   test_str("t1"      , Some(TakeFile(1)));
   test_str(" t1"     , Some(TakeFile(1)));
   test_str(" t  1"   , Some(TakeFile(1)));
   test_str(" t  1  " , Some(TakeFile(1)));
   test_str(" t  1  2", None);
   test_str("d12"     , Some(ShowDiffWith(12)));
   test_str("d13"     , None);
   test_str("d"       , None);
   test_str("d1 2"    , Some(ShowDiffBetween(1, 2)));
   test_str("d1    2" , Some(ShowDiffBetween(1, 2)));
   test_str("d  1  2" , Some(ShowDiffBetween(1, 2)));
   test_str("D  1  2" , Some(ShowDiffBetween(1, 2)));
   test_str("  m  "   , Some(MoveToTrash));
   test_str("m  "     , Some(MoveToTrash));
   test_str("M  "     , Some(MoveToTrash));
   test_str("M  1"    , None);
   test_str("s"       , Some(Skip));
   test_str("q"       , Some(Quit));
   test_str("qq"      , None);
   test_str("h"       , Some(Help));
   test_str("?"       , Some(Help));
}

#[cfg(test)]
fn test_str(input: &str, reply: Option<UserReply>)
{
   println!("test: {}", input);
   assert_eq!(parse(&input.to_string(), 12), reply);
}
<commit_msg>Remove unused import<commit_after>use parser::Parser;

pub use self::UserReply::{
   TakeFile,
   MoveToTrash,
   ShowDiff,
   ShowDiffWith,
   ShowDiffBetween,
   Skip,
   Quit,
   Help
};

pub type FileNum = uint;

#[deriving(Show, PartialEq, Eq)]
pub enum UserReply
{
   TakeFile(FileNum),
   MoveToTrash,
   ShowDiff,
   ShowDiffWith(FileNum),
   ShowDiffBetween(FileNum, FileNum),
   Skip,
   Quit,
   Help
}

pub fn parse(input: &String, num_conf_files: uint) -> Option<UserReply>
{
   if input.is_empty() || num_conf_files == 0 {
      return None;
   }

   let lowercase_input: String = input.chars()
                                      .map(|c| c.to_lowercase())
                                      .collect();

   let mut parser = Parser::new(lowercase_input.as_slice());
   parser.skip_whitespace();
   match parser.take_char() {
      Err(..) => None,

      Ok(c)   => {
         parser.skip_whitespace();
         let nothing_left = parser.eof();
         let uints = take_uints(&mut parser);
         match c {
            't' => {
               match uints.len() {
                  1 if valid_file_num(uints[0], num_conf_files)
                  => Some(TakeFile(uints[0])),

                  _ => None
               }
            }

            'd' => {
               match uints.len() {
                  0 if num_conf_files == 1
                  => Some(ShowDiff),

                  1 if valid_file_num(uints[0], num_conf_files)
                  => Some(ShowDiffWith(uints[0])),

                  2 if valid_file_num(uints[0], num_conf_files) && valid_file_num(uints[1], num_conf_files)
                  => Some(ShowDiffBetween(uints[0], uints[1])),

                  _ => None
               }
            }

            'm'      if nothing_left => Some(MoveToTrash),
            's'      if nothing_left => Some(Skip),
            'q'      if nothing_left => Some(Quit),
            'h' |'?' if nothing_left => Some(Help),

            _ => None,
         }
      }
   }
}

fn valid_file_num(file_num: uint, num_confs: uint) -> bool
{
   file_num > 0 && file_num <= num_confs
}

fn take_uints(parser: &mut Parser) -> Vec<uint>
{
   let mut uints  = Vec::new();
   while ! parser.eof() {
      parser.skip_whitespace();
      match parser.take_uint() {
         Ok(uint) => uints.push(uint),
         Err(..)  => break
      }
   }

   uints
}

#[test]
fn tests()
{
   test_str("t"       , None);
   test_str("t1"      , Some(TakeFile(1)));
   test_str(" t1"     , Some(TakeFile(1)));
   test_str(" t  1"   , Some(TakeFile(1)));
   test_str(" t  1  " , Some(TakeFile(1)));
   test_str(" t  1  2", None);
   test_str("d12"     , Some(ShowDiffWith(12)));
   test_str("d13"     , None);
   test_str("d"       , None);
   test_str("d1 2"    , Some(ShowDiffBetween(1, 2)));
   test_str("d1    2" , Some(ShowDiffBetween(1, 2)));
   test_str("d  1  2" , Some(ShowDiffBetween(1, 2)));
   test_str("D  1  2" , Some(ShowDiffBetween(1, 2)));
   test_str("  m  "   , Some(MoveToTrash));
   test_str("m  "     , Some(MoveToTrash));
   test_str("M  "     , Some(MoveToTrash));
   test_str("M  1"    , None);
   test_str("s"       , Some(Skip));
   test_str("q"       , Some(Quit));
   test_str("qq"      , None);
   test_str("h"       , Some(Help));
   test_str("?"       , Some(Help));
}

#[cfg(test)]
fn test_str(input: &str, reply: Option<UserReply>)
{
   println!("test: {}", input);
   assert_eq!(parse(&input.to_string(), 12), reply);
}
<|endoftext|>


<commit_before>/*!
The representation of CSS property values

Enums are named after the property. Variants have the same name + the
name of the value used in the spec. This leads to some verbose names,
e.g.:

The property 'background-color' and the specified value called '<color>'
in the spec lead to the variant CSSBackgroundColorColor(Color).

At least it's consistent though.
*/

use cmp::Eq;
use std::net::url::Url;
use netsurfcss::stylesheet::CssStylesheet;
use units::{Length, AbsoluteSize, RelativeSize,
            BoxSizing, BoxLength, BoxPercent, BoxAuto, Px, Em, Pt};
use units::GenericFontFamily;
use color::Color;
use std::cmp::FuzzyEq;

/** A partial CSS value, before inheritance has been resolved */
enum CSSValue<T> {
    Inherit,
    Specified(T),
}

// CSS 2.1, Section 8 - Box model

enum CSSMargin {
    CSSMarginLength(Length),
    CSSMarginPercentage(float),
    CSSMarginAuto
}

enum CSSPadding {
    CSSPaddingLength(Length),
    CSSPaddingPercentage(float)
}

enum CSSBorderWidth {
    CSSBorderWidthThin,
    CSSBorderWidthMedium,
    CSSBorderWidthThick,
    CSSBorderWidthLength(Length)
}

enum CSSBorderColor {
    CSSBorderColorColor(Color),
    CSSBorderColorTransparent
}

enum CSSBorderStyle {
    CSSBorderStyleNone,
    CSSBorderStyleHidden,
    CSSBorderStyleDotted,
    CSSBorderStyleDashed,
    CSSBorderStyleSolid,
    CSSBorderStyleDouble,
    CSSBorderStyleGroove,
    CSSBorderStyleRidge,
    CSSBorderStyleInset,
    CSSBorderStyleOutset,
}

// CSS 2.1, Section 9 - Visual formatting model

enum CSSDisplay {
    CSSDisplayInline,
    CSSDisplayBlock,
    CSSDisplayListItem,
    CSSDisplayInlineBlock,
    CSSDisplayTable,
    CSSDisplayInlineTable,
    CSSDisplayTableRowGroup,
    CSSDisplayTableHeaderGroup,
    CSSDisplayTableFooterGroup,
    CSSDisplayTableRow,
    CSSDisplayTableColumnGroup,
    CSSDisplayTableColumn,
    CSSDisplayTableCell,
    CSSDisplayTableCaption,
    CSSDisplayNone
}

enum CSSPosition {
    CSSPositionStatic,
    CSSPositionRelative,
    CSSPositionAbsolute,
    CSSPositionFixed
}

enum CSSTop {
    CSSTopLength(Length),
    CSSTopPercentage,
    CSSTopAuto
}

enum CSSRight {
    CSSRightLength(Length),
    CSSRightPercentage(float),
    CSSRightAuto
}

enum CSSBottom {
    CSSBottomLength(Length),
    CSSBottomPercentage(float),
    CSSBottomAuto
}

enum CSSLeft {
    CSSLeftLength(Length),
    CSSLeftPercentage(float),
    CSSLeftAuto
}

enum CSSFloat {
    CSSFloatLeft,
    CSSFloatRight,
    CSSFloatNone
}

enum CSSDirection {
    CSSDirectionLtr,
    CSSDirectionRtl
}

// CSS 2.1, Section 10 - Visual formatting model details

enum CSSWidth {
    CSSWidthLength(Length),
    CSSWidthPercentage(float),
    CSSWidthAuto
}

enum CSSHeight {
    CSSHeightLength(Length),
    CSSHeightPercentage(float),
    CSSHeightAuto
}

enum CSSLineHeight {
    CSSLineHeightNormal,
    CSSLineHeightNumber(float),
    CSSLineHeightLength(Length),
    CSSLineHeightPercentage(float),
}

enum CSSVerticalAlign {
    CSSVerticalAlignBaseline,
    CSSVerticalAlignSub,
    CSSVerticalAlignSuper,
    CSSVerticalAlignTop,
    CSSVerticalAlignTextTop,
    CSSVerticalAlignMiddle,
    CSSVerticalAlignBottom,
    CSSVerticalAlignTextBottom,
    CSSVerticalAlignPercentage(float),
    CSSVerticalAlignLength(Length),
}

// CSS 2.1, Section 11 - Visual effects

enum CSSOverflow {
    CSSOverflowVisible,
    CSSOverflowHidden,
    CSSOverflowScroll,
    CSSOverflowAuto
}

enum CSSVisibility {
    CSSVisibilityVisible,
    CSSVisibilityHidden,
    CSSVisibilityCollapse
}

// CSS 2.1, Section 12 - Generated content, automatic numbering, and lists

// CSS 2.1, Section 13 - Paged media

// CSS 2.1, Section 14 - Colors and Backgrounds

enum CSSColor {
    CSSColorColor(Color)
}

enum CSSBackgroundColor {
    CSSBackgroundColorColor(Color),
    CSSBackgroundColorTransparent
}

enum CSSBackgroundImage {
    CSSBackgroundUri(Url),
    CSSBackgroundImageNone
}

enum CSSBackgroundRepeat {
    CSSBackgroundRepeatRepeat,
    CSSBackgroundRepeatRepeatX,
    CSSBackgroundRepeatRepeatY,
    CSSBackgroundRepeatNoRepeat
}

enum CSSBackgroundAttachment {
    CSSBackgroundAttachmentScroll,
    CSSBackgroundAttachmentFixed
}

enum CSSBackgroundPosition {
    CSSBackgroundPositionPercentage(float),
    CSSBackgroundPositionLength(Length),
    CSSBackgroundPositionLeft,
    CSSBackgroundPositionCenter,
    CSSBackgroundPositionRight,
    CSSBackgroundPositionTop,
    CSSBackgroundPositionBottom
}

// CSS 2.1, Section 15 - Fonts

enum CSSFontFamily {
    CSSFontFamilyFamilyName(~str),
    CSSFontFamilyGenericFamily(GenericFontFamily)
}

enum CSSFontStyle {
    CSSFontStyleNormal,
    CSSFontStyleItalic,
    CSSFontStyleOblique
}

enum CSSFontWeight {
    CSSFontWeightNormal,
    CSSFontWeightBold,
    CSSFontWeightBolder,
    CSSFontWeightLighter,
    CSSFontWeight100,
    CSSFontWeight200,
    CSSFontWeight300,
    CSSFontWeight400,
    CSSFontWeight500,
    CSSFontWeight600,
    CSSFontWeight700,
    CSSFontWeight800,
    CSSFontWeight900
}

enum CSSFontSize {
    CSSFontSizeAbsoluteSize(AbsoluteSize),
    CSSFontSizeRelativeSize(RelativeSize),
    CSSFontSizeLength(Length),
    CSSFontSizePercentage(float)
}

// CSS 2.1, Section 16 - Text

enum CSSTextAlign {
    CSSTextAlignLeft,
    CSSTextAlignRight,
    CSSTextAlignCenter,
    CSSTextAlignJustify
}

enum CSSTextDecoration {
    CSSTextDecorationNone,
    CSSTextDecorationUnderline,
    CSSTextDecorationOverline,
    CSSTextDecorationLineThrough,
    CSSTextDecorationBlink
}

enum CSSTextTransform {
    CSSTextTransformCapitalize,
    CSSTextTransformUppercase,
    CSSTextTransformLowercase,
    CSSTextTransformNone
}

// CSS 2.1, Section 17 - Tables

// CSS 2.1, Section 18 - User interface

// Implementations of Eq

impl Length: cmp::Eq {
    pure fn eq(&self, other: &Length) -> bool {
        match (*self, *other) {
          (Em(a), Em(b)) => a == b,
          (Px(a), Px(b)) => a == b,
          (Pt(a), Pt(b)) => a == b,
          (_, _) => false
        }
    }
    pure fn ne(&self, other: &Length) -> bool {
        return !self.eq(other);
    }
}

impl BoxSizing: cmp::Eq {
    pure fn eq(&self, other: &BoxSizing) -> bool {
        match (*self, *other) {
          (BoxLength(a), BoxLength(b)) => a == b,
          (BoxPercent(a), BoxPercent(b)) => a == b,
          (BoxAuto, BoxAuto) => true,
          (_, _) => false
        }
    }
    pure fn ne(&self, other: &BoxSizing) -> bool {
        return !self.eq(other);
    }
}

impl AbsoluteSize: cmp::Eq {
    pure fn eq(&self, other: &AbsoluteSize) -> bool {
        (*self) as uint == (*other) as uint
    }
    pure fn ne(&self, other: &AbsoluteSize) -> bool {
        return !self.eq(other);
    }
}

impl RelativeSize: cmp::Eq {
    pure fn eq(&self, other: &RelativeSize) -> bool {
        (*self) as uint == (*other) as uint
    }
    pure fn ne(&self, other: &RelativeSize) -> bool {
        return !self.eq(other);
    }
}

impl CSSBackgroundColor: cmp::Eq {
    pure fn eq(&self, other: &CSSBackgroundColor) -> bool {
        match (*self, *other) {
            (CSSBackgroundColorColor(a), CSSBackgroundColorColor(b)) => a == b,
            (CSSBackgroundColorTransparent, CSSBackgroundColorTransparent) => true,
            (_, _) => false
        }
    }
    pure fn ne(&self, other: &CSSBackgroundColor) -> bool {
        return !self.eq(other);
    }
}

impl CSSColor: cmp::Eq {
    pure fn eq(&self, other: &CSSColor) -> bool {
        match (*self, *other) {
            (CSSColorColor(a), CSSColorColor(b)) => a == b
        }
    }
    pure fn ne(&self, other: &CSSColor) -> bool {
        return !self.eq(other);
    }
}

impl CSSDisplay: cmp::Eq {
    pure fn eq(&self, other: &CSSDisplay) -> bool {
        (*self) as uint == (*other) as uint
    }
    pure fn ne(&self, other: &CSSDisplay) -> bool {
        return !self.eq(other);
    }
}

impl CSSFontSize: cmp::Eq {
    pure fn eq(&self, other: &CSSFontSize) -> bool {
        match (*self, *other) {
            (CSSFontSizeAbsoluteSize(a), CSSFontSizeAbsoluteSize(b)) => a == b,
            (CSSFontSizeRelativeSize(a), CSSFontSizeRelativeSize(b)) => a == b,
            (CSSFontSizeLength(a), CSSFontSizeLength(b)) => a == b,
            (CSSFontSizePercentage(a), CSSFontSizePercentage(b))  => a == b,
            (_, _) => false
        }
    }
    pure fn ne(&self, other: &CSSFontSize) -> bool {
        return !self.eq(other);
    }
}

impl<T: Eq> CSSValue<T> : Eq {
    pure fn eq(&self, other: &CSSValue<T>) -> bool {
        match (self, other) {
            (&Inherit, &Inherit) => true,
            (&Specified(a), &Specified(b)) => a == b,
            _ => false
        }
    }
    pure fn ne(&self, other: &CSSValue<T>) -> bool {
        return !self.eq(other);
    }
}

impl CSSBorderWidth: Eq {
    pure fn eq(&self, other: &CSSBorderWidth) -> bool {
        match (*self, *other) {
            (CSSBorderWidthThin, CSSBorderWidthThin) => true,
            (CSSBorderWidthMedium, CSSBorderWidthMedium) => true,
            (CSSBorderWidthThick, CSSBorderWidthThick) => true,
            (CSSBorderWidthLength(l1), CSSBorderWidthLength(l2)) => l1 == l2,
            (_, _) => false
        }
    }
    pure fn ne(&self, other: &CSSBorderWidth) -> bool { !self.eq(other) }
}

impl CSSMargin: Eq {
    pure fn eq(&self, other: &CSSMargin) -> bool {
        match (*self, *other) {
            (CSSMarginLength(l1), CSSMarginLength(l2)) => l1 == l2,
            (CSSMarginPercentage(p1), CSSMarginPercentage(p2)) => p1.fuzzy_eq(&p2),
            (CSSMarginAuto, CSSMarginAuto) => true,
            (_, _) => false
        }
    }

    pure fn ne(&self, other: &CSSMargin) -> bool { !self.eq(other) }
}

impl CSSFloat: Eq {
    pure fn eq(&self, other: &CSSFloat) -> bool {
        match (*self, *other) {
            (CSSFloatLeft, CSSFloatLeft) => true,
            (CSSFloatRight, CSSFloatRight) => true,
            (CSSFloatNone, CSSFloatNone) => true,
            (_, _) => false
        }
    }

    pure fn ne(&self, other: &CSSFloat) -> bool { !self.eq(other) }
}

impl CSSPosition: Eq {
    pure fn eq(&self, other: &CSSPosition) -> bool {
        match (*self, *other) {
            (CSSPositionStatic, CSSPositionStatic) => true,
            (CSSPositionRelative, CSSPositionRelative) => true,
            (CSSPositionAbsolute, CSSPositionAbsolute) => true,
            (CSSPositionFixed, CSSPositionFixed) => true,
            (_, _) => false
        }
    }

    pure fn ne(&self, other: &CSSPosition) -> bool { !self.eq(other) }
}

impl CSSWidth: Eq {
    pure fn eq(&self, other: &CSSWidth) -> bool {
        match (*self, *other) {
            (CSSWidthLength(l1), CSSWidthLength(l2)) => l1 == l2,
            (CSSWidthPercentage(p1), CSSWidthPercentage(p2)) => p1.fuzzy_eq(&p2),
            (CSSWidthAuto, CSSWidthAuto) => true,
            (_, _) => false
        }
    }

    pure fn ne(&self, other: &CSSWidth) -> bool { !self.eq(other) }
}

impl CSSHeight: Eq {
    pure fn eq(&self, other: &CSSHeight) -> bool {
        match (*self, *other) {
            (CSSHeightLength(l1), CSSHeightLength(l2)) => l1 == l2,
            (CSSHeightPercentage(p1), CSSHeightPercentage(p2)) => p1.fuzzy_eq(&p2),
            (CSSHeightAuto, CSSHeightAuto) => true,
            (_, _) => false
        }
    }

    pure fn ne(&self, other: &CSSHeight) -> bool { !self.eq(other) }
}

impl CSSFontFamily: Eq {
    pure fn eq(&self, other: &CSSFontFamily) -> bool {
        match (self, other) {
            (&CSSFontFamilyFamilyName(ref f1), &CSSFontFamilyFamilyName(ref f2)) => f1 == f2,
            (&CSSFontFamilyGenericFamily(g1), &CSSFontFamilyGenericFamily(g2)) => g1 == g2,
            (_, _) => false
        }
    }

    pure fn ne(&self, other: &CSSFontFamily) -> bool { !self.eq(other) }
}

impl CSSFontStyle: Eq {
    pure fn eq(&self, other: &CSSFontStyle) -> bool {
        (*self) as uint == *other as uint
    }

    pure fn ne(&self, other: &CSSFontStyle) -> bool { !self.eq(other) }
}

impl CSSFontWeight: Eq {
    pure fn eq(&self, other: &CSSFontWeight) -> bool {
        (*self) as uint == *other as uint
    }

    pure fn ne(&self, other: &CSSFontWeight) -> bool { !self.eq(other) }
}

impl CSSTextAlign: Eq {
    pure fn eq(&self, other: &CSSTextAlign) -> bool {
        (*self) as uint == *other as uint
    }

    pure fn ne(&self, other: &CSSTextAlign) -> bool { !self.eq(other) }
}

impl CSSLineHeight: Eq {
    pure fn eq(&self, other: &CSSLineHeight) -> bool {
        match (*self, *other) {
            (CSSLineHeightNormal, CSSLineHeightNormal) => true,
            (CSSLineHeightNumber(n1), CSSLineHeightNumber(n2)) => n1 == n2,
            (CSSLineHeightLength(n1), CSSLineHeightLength(n2)) => n1 == n2,
            (CSSLineHeightPercentage(n1), CSSLineHeightPercentage(n2)) => n1 == n2,
            (_, _) => false
        }
    }

    pure fn ne(&self, other: &CSSLineHeight) -> bool { !self.eq(other) }
}
<commit_msg>Update for langugae changes.<commit_after>/*!
The representation of CSS property values

Enums are named after the property. Variants have the same name + the
name of the value used in the spec. This leads to some verbose names,
e.g.:

The property 'background-color' and the specified value called '<color>'
in the spec lead to the variant CSSBackgroundColorColor(Color).

At least it's consistent though.
*/

use cmp::Eq;
use std::net::url::Url;
use netsurfcss::stylesheet::CssStylesheet;
use units::{Length, AbsoluteSize, RelativeSize,
            BoxSizing, BoxLength, BoxPercent, BoxAuto, Px, Em, Pt};
use units::GenericFontFamily;
use color::Color;
use std::cmp::FuzzyEq;

/** A partial CSS value, before inheritance has been resolved */
enum CSSValue<T> {
    Inherit,
    Specified(T),
}

// CSS 2.1, Section 8 - Box model

enum CSSMargin {
    CSSMarginLength(Length),
    CSSMarginPercentage(float),
    CSSMarginAuto
}

enum CSSPadding {
    CSSPaddingLength(Length),
    CSSPaddingPercentage(float)
}

enum CSSBorderWidth {
    CSSBorderWidthThin,
    CSSBorderWidthMedium,
    CSSBorderWidthThick,
    CSSBorderWidthLength(Length)
}

enum CSSBorderColor {
    CSSBorderColorColor(Color),
    CSSBorderColorTransparent
}

enum CSSBorderStyle {
    CSSBorderStyleNone,
    CSSBorderStyleHidden,
    CSSBorderStyleDotted,
    CSSBorderStyleDashed,
    CSSBorderStyleSolid,
    CSSBorderStyleDouble,
    CSSBorderStyleGroove,
    CSSBorderStyleRidge,
    CSSBorderStyleInset,
    CSSBorderStyleOutset,
}

// CSS 2.1, Section 9 - Visual formatting model

enum CSSDisplay {
    CSSDisplayInline,
    CSSDisplayBlock,
    CSSDisplayListItem,
    CSSDisplayInlineBlock,
    CSSDisplayTable,
    CSSDisplayInlineTable,
    CSSDisplayTableRowGroup,
    CSSDisplayTableHeaderGroup,
    CSSDisplayTableFooterGroup,
    CSSDisplayTableRow,
    CSSDisplayTableColumnGroup,
    CSSDisplayTableColumn,
    CSSDisplayTableCell,
    CSSDisplayTableCaption,
    CSSDisplayNone
}

enum CSSPosition {
    CSSPositionStatic,
    CSSPositionRelative,
    CSSPositionAbsolute,
    CSSPositionFixed
}

enum CSSTop {
    CSSTopLength(Length),
    CSSTopPercentage,
    CSSTopAuto
}

enum CSSRight {
    CSSRightLength(Length),
    CSSRightPercentage(float),
    CSSRightAuto
}

enum CSSBottom {
    CSSBottomLength(Length),
    CSSBottomPercentage(float),
    CSSBottomAuto
}

enum CSSLeft {
    CSSLeftLength(Length),
    CSSLeftPercentage(float),
    CSSLeftAuto
}

enum CSSFloat {
    CSSFloatLeft,
    CSSFloatRight,
    CSSFloatNone
}

enum CSSDirection {
    CSSDirectionLtr,
    CSSDirectionRtl
}

// CSS 2.1, Section 10 - Visual formatting model details

enum CSSWidth {
    CSSWidthLength(Length),
    CSSWidthPercentage(float),
    CSSWidthAuto
}

enum CSSHeight {
    CSSHeightLength(Length),
    CSSHeightPercentage(float),
    CSSHeightAuto
}

enum CSSLineHeight {
    CSSLineHeightNormal,
    CSSLineHeightNumber(float),
    CSSLineHeightLength(Length),
    CSSLineHeightPercentage(float),
}

enum CSSVerticalAlign {
    CSSVerticalAlignBaseline,
    CSSVerticalAlignSub,
    CSSVerticalAlignSuper,
    CSSVerticalAlignTop,
    CSSVerticalAlignTextTop,
    CSSVerticalAlignMiddle,
    CSSVerticalAlignBottom,
    CSSVerticalAlignTextBottom,
    CSSVerticalAlignPercentage(float),
    CSSVerticalAlignLength(Length),
}

// CSS 2.1, Section 11 - Visual effects

enum CSSOverflow {
    CSSOverflowVisible,
    CSSOverflowHidden,
    CSSOverflowScroll,
    CSSOverflowAuto
}

enum CSSVisibility {
    CSSVisibilityVisible,
    CSSVisibilityHidden,
    CSSVisibilityCollapse
}

// CSS 2.1, Section 12 - Generated content, automatic numbering, and lists

// CSS 2.1, Section 13 - Paged media

// CSS 2.1, Section 14 - Colors and Backgrounds

enum CSSColor {
    CSSColorColor(Color)
}

enum CSSBackgroundColor {
    CSSBackgroundColorColor(Color),
    CSSBackgroundColorTransparent
}

enum CSSBackgroundImage {
    CSSBackgroundUri(Url),
    CSSBackgroundImageNone
}

enum CSSBackgroundRepeat {
    CSSBackgroundRepeatRepeat,
    CSSBackgroundRepeatRepeatX,
    CSSBackgroundRepeatRepeatY,
    CSSBackgroundRepeatNoRepeat
}

enum CSSBackgroundAttachment {
    CSSBackgroundAttachmentScroll,
    CSSBackgroundAttachmentFixed
}

enum CSSBackgroundPosition {
    CSSBackgroundPositionPercentage(float),
    CSSBackgroundPositionLength(Length),
    CSSBackgroundPositionLeft,
    CSSBackgroundPositionCenter,
    CSSBackgroundPositionRight,
    CSSBackgroundPositionTop,
    CSSBackgroundPositionBottom
}

// CSS 2.1, Section 15 - Fonts

enum CSSFontFamily {
    CSSFontFamilyFamilyName(~str),
    CSSFontFamilyGenericFamily(GenericFontFamily)
}

enum CSSFontStyle {
    CSSFontStyleNormal,
    CSSFontStyleItalic,
    CSSFontStyleOblique
}

enum CSSFontWeight {
    CSSFontWeightNormal,
    CSSFontWeightBold,
    CSSFontWeightBolder,
    CSSFontWeightLighter,
    CSSFontWeight100,
    CSSFontWeight200,
    CSSFontWeight300,
    CSSFontWeight400,
    CSSFontWeight500,
    CSSFontWeight600,
    CSSFontWeight700,
    CSSFontWeight800,
    CSSFontWeight900
}

enum CSSFontSize {
    CSSFontSizeAbsoluteSize(AbsoluteSize),
    CSSFontSizeRelativeSize(RelativeSize),
    CSSFontSizeLength(Length),
    CSSFontSizePercentage(float)
}

// CSS 2.1, Section 16 - Text

enum CSSTextAlign {
    CSSTextAlignLeft,
    CSSTextAlignRight,
    CSSTextAlignCenter,
    CSSTextAlignJustify
}

enum CSSTextDecoration {
    CSSTextDecorationNone,
    CSSTextDecorationUnderline,
    CSSTextDecorationOverline,
    CSSTextDecorationLineThrough,
    CSSTextDecorationBlink
}

enum CSSTextTransform {
    CSSTextTransformCapitalize,
    CSSTextTransformUppercase,
    CSSTextTransformLowercase,
    CSSTextTransformNone
}

// CSS 2.1, Section 17 - Tables

// CSS 2.1, Section 18 - User interface

// Implementations of Eq

impl Length: cmp::Eq {
    pure fn eq(&self, other: &Length) -> bool {
        match (*self, *other) {
          (Em(a), Em(b)) => a == b,
          (Px(a), Px(b)) => a == b,
          (Pt(a), Pt(b)) => a == b,
          (_, _) => false
        }
    }
    pure fn ne(&self, other: &Length) -> bool {
        return !self.eq(other);
    }
}

impl BoxSizing: cmp::Eq {
    pure fn eq(&self, other: &BoxSizing) -> bool {
        match (*self, *other) {
          (BoxLength(a), BoxLength(b)) => a == b,
          (BoxPercent(a), BoxPercent(b)) => a == b,
          (BoxAuto, BoxAuto) => true,
          (_, _) => false
        }
    }
    pure fn ne(&self, other: &BoxSizing) -> bool {
        return !self.eq(other);
    }
}

impl AbsoluteSize: cmp::Eq {
    pure fn eq(&self, other: &AbsoluteSize) -> bool {
        (*self) as uint == (*other) as uint
    }
    pure fn ne(&self, other: &AbsoluteSize) -> bool {
        return !self.eq(other);
    }
}

impl RelativeSize: cmp::Eq {
    pure fn eq(&self, other: &RelativeSize) -> bool {
        (*self) as uint == (*other) as uint
    }
    pure fn ne(&self, other: &RelativeSize) -> bool {
        return !self.eq(other);
    }
}

impl CSSBackgroundColor: cmp::Eq {
    pure fn eq(&self, other: &CSSBackgroundColor) -> bool {
        match (*self, *other) {
            (CSSBackgroundColorColor(a), CSSBackgroundColorColor(b)) => a == b,
            (CSSBackgroundColorTransparent, CSSBackgroundColorTransparent) => true,
            (_, _) => false
        }
    }
    pure fn ne(&self, other: &CSSBackgroundColor) -> bool {
        return !self.eq(other);
    }
}

impl CSSColor: cmp::Eq {
    pure fn eq(&self, other: &CSSColor) -> bool {
        match (*self, *other) {
            (CSSColorColor(a), CSSColorColor(b)) => a == b
        }
    }
    pure fn ne(&self, other: &CSSColor) -> bool {
        return !self.eq(other);
    }
}

impl CSSDisplay: cmp::Eq {
    pure fn eq(&self, other: &CSSDisplay) -> bool {
        (*self) as uint == (*other) as uint
    }
    pure fn ne(&self, other: &CSSDisplay) -> bool {
        return !self.eq(other);
    }
}

impl CSSFontSize: cmp::Eq {
    pure fn eq(&self, other: &CSSFontSize) -> bool {
        match (*self, *other) {
            (CSSFontSizeAbsoluteSize(a), CSSFontSizeAbsoluteSize(b)) => a == b,
            (CSSFontSizeRelativeSize(a), CSSFontSizeRelativeSize(b)) => a == b,
            (CSSFontSizeLength(a), CSSFontSizeLength(b)) => a == b,
            (CSSFontSizePercentage(a), CSSFontSizePercentage(b))  => a == b,
            (_, _) => false
        }
    }
    pure fn ne(&self, other: &CSSFontSize) -> bool {
        return !self.eq(other);
    }
}

impl<T: Eq> CSSValue<T> : Eq {
    pure fn eq(&self, other: &CSSValue<T>) -> bool {
        match (self, other) {
            (&Inherit, &Inherit) => true,
            (&Specified(ref a), &Specified(ref b)) => a == b,
            _ => false
        }
    }
    pure fn ne(&self, other: &CSSValue<T>) -> bool {
        return !self.eq(other);
    }
}

impl CSSBorderWidth: Eq {
    pure fn eq(&self, other: &CSSBorderWidth) -> bool {
        match (*self, *other) {
            (CSSBorderWidthThin, CSSBorderWidthThin) => true,
            (CSSBorderWidthMedium, CSSBorderWidthMedium) => true,
            (CSSBorderWidthThick, CSSBorderWidthThick) => true,
            (CSSBorderWidthLength(l1), CSSBorderWidthLength(l2)) => l1 == l2,
            (_, _) => false
        }
    }
    pure fn ne(&self, other: &CSSBorderWidth) -> bool { !self.eq(other) }
}

impl CSSMargin: Eq {
    pure fn eq(&self, other: &CSSMargin) -> bool {
        match (*self, *other) {
            (CSSMarginLength(l1), CSSMarginLength(l2)) => l1 == l2,
            (CSSMarginPercentage(p1), CSSMarginPercentage(p2)) => p1.fuzzy_eq(&p2),
            (CSSMarginAuto, CSSMarginAuto) => true,
            (_, _) => false
        }
    }

    pure fn ne(&self, other: &CSSMargin) -> bool { !self.eq(other) }
}

impl CSSFloat: Eq {
    pure fn eq(&self, other: &CSSFloat) -> bool {
        match (*self, *other) {
            (CSSFloatLeft, CSSFloatLeft) => true,
            (CSSFloatRight, CSSFloatRight) => true,
            (CSSFloatNone, CSSFloatNone) => true,
            (_, _) => false
        }
    }

    pure fn ne(&self, other: &CSSFloat) -> bool { !self.eq(other) }
}

impl CSSPosition: Eq {
    pure fn eq(&self, other: &CSSPosition) -> bool {
        match (*self, *other) {
            (CSSPositionStatic, CSSPositionStatic) => true,
            (CSSPositionRelative, CSSPositionRelative) => true,
            (CSSPositionAbsolute, CSSPositionAbsolute) => true,
            (CSSPositionFixed, CSSPositionFixed) => true,
            (_, _) => false
        }
    }

    pure fn ne(&self, other: &CSSPosition) -> bool { !self.eq(other) }
}

impl CSSWidth: Eq {
    pure fn eq(&self, other: &CSSWidth) -> bool {
        match (*self, *other) {
            (CSSWidthLength(l1), CSSWidthLength(l2)) => l1 == l2,
            (CSSWidthPercentage(p1), CSSWidthPercentage(p2)) => p1.fuzzy_eq(&p2),
            (CSSWidthAuto, CSSWidthAuto) => true,
            (_, _) => false
        }
    }

    pure fn ne(&self, other: &CSSWidth) -> bool { !self.eq(other) }
}

impl CSSHeight: Eq {
    pure fn eq(&self, other: &CSSHeight) -> bool {
        match (*self, *other) {
            (CSSHeightLength(l1), CSSHeightLength(l2)) => l1 == l2,
            (CSSHeightPercentage(p1), CSSHeightPercentage(p2)) => p1.fuzzy_eq(&p2),
            (CSSHeightAuto, CSSHeightAuto) => true,
            (_, _) => false
        }
    }

    pure fn ne(&self, other: &CSSHeight) -> bool { !self.eq(other) }
}

impl CSSFontFamily: Eq {
    pure fn eq(&self, other: &CSSFontFamily) -> bool {
        match (self, other) {
            (&CSSFontFamilyFamilyName(ref f1), &CSSFontFamilyFamilyName(ref f2)) => f1 == f2,
            (&CSSFontFamilyGenericFamily(g1), &CSSFontFamilyGenericFamily(g2)) => g1 == g2,
            (_, _) => false
        }
    }

    pure fn ne(&self, other: &CSSFontFamily) -> bool { !self.eq(other) }
}

impl CSSFontStyle: Eq {
    pure fn eq(&self, other: &CSSFontStyle) -> bool {
        (*self) as uint == *other as uint
    }

    pure fn ne(&self, other: &CSSFontStyle) -> bool { !self.eq(other) }
}

impl CSSFontWeight: Eq {
    pure fn eq(&self, other: &CSSFontWeight) -> bool {
        (*self) as uint == *other as uint
    }

    pure fn ne(&self, other: &CSSFontWeight) -> bool { !self.eq(other) }
}

impl CSSTextAlign: Eq {
    pure fn eq(&self, other: &CSSTextAlign) -> bool {
        (*self) as uint == *other as uint
    }

    pure fn ne(&self, other: &CSSTextAlign) -> bool { !self.eq(other) }
}

impl CSSLineHeight: Eq {
    pure fn eq(&self, other: &CSSLineHeight) -> bool {
        match (*self, *other) {
            (CSSLineHeightNormal, CSSLineHeightNormal) => true,
            (CSSLineHeightNumber(n1), CSSLineHeightNumber(n2)) => n1 == n2,
            (CSSLineHeightLength(n1), CSSLineHeightLength(n2)) => n1 == n2,
            (CSSLineHeightPercentage(n1), CSSLineHeightPercentage(n2)) => n1 == n2,
            (_, _) => false
        }
    }

    pure fn ne(&self, other: &CSSLineHeight) -> bool { !self.eq(other) }
}
<|endoftext|>


<commit_before>use pnet::packet::tcp::TcpPacket;
use serde_json::{Value, Map, Number};

pub struct TcpHeader {
	source_port: Number,
	destination_port: Number,
	sequence_number: Number,
	ack_number: Number,
	data_offset: Number,
	flags: Number,
	window_size: Number,
	checksum: Number,
	urgent_pointer: Number,
}

impl TcpHeader {
	pub fn new(p: &TcpPacket) -> TcpHeader {
		TcpHeader {
			source_port: Number::from(p.get_source()),
			destination_port: Number::from(p.get_destination()),
			sequence_number: Number::from(p.get_sequence()),
			ack_number: Number::from(p.get_acknowledgement()),
			data_offset: Number::from(p.get_data_offset()),
			flags: Number::from(p.get_flags()),
			window_size: Number::from(p.get_window()),
			checksum: Number::from(p.get_checksum()),
			urgent_pointer: Number::from(p.get_urgent_ptr()),
		}
	}

	pub fn to_json_map(&self) -> Map<String, Value> {
		let mut header = Map::new();

		header.insert("source_port".to_string(), Value::Number(self.source_port.clone()));
		header.insert("destination_port".to_string(), Value::Number(self.destination_port.clone()));
		header.insert("sequence_number".to_string(), Value::Number(self.sequence_number.clone()));
		header.insert("ack_number".to_string(), Value::Number(self.ack_number.clone()));
		header.insert("data_offset".to_string(), Value::Number(self.data_offset.clone()));
		header.insert("flags".to_string(), Value::Number(self.flags.clone()));
		header.insert("window_size".to_string(), Value::Number(self.window_size.clone()));
		header.insert("checksum".to_string(), Value::Number(self.checksum.clone()));
		header.insert("urgent_pointer".to_string(), Value::Number(self.urgent_pointer.clone()));

		header
	}
}<commit_msg>Use vector for TCP flags<commit_after>use pnet::packet::tcp::{TcpPacket, TcpFlags};
use serde_json::{Value, Map, Number};

pub struct TcpHeader {
	source_port: Number,
	destination_port: Number,
	sequence_number: Number,
	ack_number: Number,
	data_offset: Number,
	flags: Value,
	window_size: Number,
	checksum: Number,
	urgent_pointer: Number,
}

impl TcpHeader {
	pub fn new(p: &TcpPacket) -> TcpHeader {
		let flags_number = p.get_flags();
		let mut flags: Vec<&str> = Vec::new();

		if (flags_number & TcpFlags::ACK) == TcpFlags::ACK {
			flags.push("ACK")
		}
		if (flags_number & TcpFlags::CWR) == TcpFlags::CWR {
			flags.push("CWR")
		}
		if (flags_number & TcpFlags::ECE) == TcpFlags::ECE {
			flags.push("ECE")
		}
		if (flags_number & TcpFlags::FIN) == TcpFlags::FIN {
			flags.push("FIN")
		}
		if (flags_number & TcpFlags::NS) == TcpFlags::NS {
			flags.push("NS")
		}
		if (flags_number & TcpFlags::PSH) == TcpFlags::PSH {
			flags.push("PSH")
		}
		if (flags_number & TcpFlags::RST) == TcpFlags::RST {
			flags.push("RST")
		}
		if (flags_number & TcpFlags::SYN) == TcpFlags::SYN {
			flags.push("SYN")
		}
		if (flags_number & TcpFlags::URG) == TcpFlags::URG {
			flags.push("URG")
		}

		TcpHeader {
			source_port: Number::from(p.get_source()),
			destination_port: Number::from(p.get_destination()),
			sequence_number: Number::from(p.get_sequence()),
			ack_number: Number::from(p.get_acknowledgement()),
			data_offset: Number::from(p.get_data_offset()),
			flags: Value::from(flags),
			window_size: Number::from(p.get_window()),
			checksum: Number::from(p.get_checksum()),
			urgent_pointer: Number::from(p.get_urgent_ptr()),
		}
	}

	pub fn to_json_map(&self) -> Map<String, Value> {
		let mut header = Map::new();

		header.insert("source_port".to_string(), Value::Number(self.source_port.clone()));
		header.insert("destination_port".to_string(), Value::Number(self.destination_port.clone()));
		header.insert("sequence_number".to_string(), Value::Number(self.sequence_number.clone()));
		header.insert("ack_number".to_string(), Value::Number(self.ack_number.clone()));
		header.insert("data_offset".to_string(), Value::Number(self.data_offset.clone()));
		header.insert("flags".to_string(), self.flags.clone());
		header.insert("window_size".to_string(), Value::Number(self.window_size.clone()));
		header.insert("checksum".to_string(), Value::Number(self.checksum.clone()));
		header.insert("urgent_pointer".to_string(), Value::Number(self.urgent_pointer.clone()));

		header
	}
}<|endoftext|>


<commit_before>use super::mode;
use super::string_utils;

#[deriving(Clone)]
#[deriving(Show)]
enum DOC {
    Nil,
    Append(Box<Doc>, Box<Doc>),
    Break(uint, uint),
    Group(Box<Doc>),
    Nest(uint, Box<Doc>),
    Newline,
    Text(String),
}

pub type Doc = DOC;

fn fitting(xs:Vec<(uint,mode::Mode,Doc)>, left:uint) -> bool {
    match xs.as_slice() {
        [] => {
            true
        },
        [(i, mode, ref doc), rest..] => match doc.clone() {
            Nil => {
                fitting(rest.to_vec(), left)
            },
            Append(box x, box y) => {
                let mut ys = vec![(i, mode, x), (i, mode, y)];
                ys.push_all(rest);
                fitting(ys, left)
            },
            Nest(j, box x) => {
                let mut ys = vec![(i + j, mode, x)];
                ys.push_all(rest);
                fitting(ys, left)
            },
            Text(str) => {
                fitting(rest.to_vec(), left - str.len())
            },
            Break(sp, _) => match mode {
                mode::Flat => {
                    fitting(rest.to_vec(), left - sp)
                },
                mode::Break => {
                    true
                },
            },
            Newline => {
                true
            },
            Group(box x) => {
                let mut ys = vec![(i, mode, x)];
                ys.push_all(rest);
                fitting(ys, left)
            },
        }
    }
}

fn prepend<A:Clone>(mut v: Vec<A>, x:A) -> Vec<A> {
    // let mut res = v;
    v.insert(0, x);
    v
}

fn best(w:uint, s:Vec<String>, x:Doc) -> Vec<String> {
    fn go(w:uint, s:Vec<String>, k:uint, xs:Vec<(uint,mode::Mode,Doc)>) -> Vec<String> {
        match xs.as_slice() {
            [] => s,
            [(i, mode, ref doc), rest..] => match doc.clone() {
                Nil => {
                    go(w, s, k, rest.to_vec())
                },
                Append(box x, box y) => {
                    let mut zs = vec![(i, mode, x), (i, mode, y)];
                    zs.push_all(rest);
                    go(w, s, k, zs)
                },
                Nest(j, box x) => {
                    let mut zs = vec![(i + j, mode, x)];
                    zs.push_all(rest);
                    go(w, s, k, zs)
                },
                Text(str) => {
                    go(w, prepend(s, str.clone()), k + str.len(), rest.to_vec())
                },
                Newline => {
                    go(w, prepend(s, string_utils::nl_space(i)), i, rest.to_vec())
                },
                Break(sp, off) => {
                    match mode {
                        mode::Flat => {
                            go(w, prepend(s, string_utils::spaces(sp)), k + sp, rest.to_vec())
                        },
                        mode::Break => {
                            go(w, prepend(s, string_utils::nl_space(i + off)), i + off, rest.to_vec())
                        }
                    }
                },
                Group(box x) => {
                    match mode {
                        mode::Flat => {
                            let mut zs = vec![(i, mode::Flat, x)];
                            zs.push_all(rest);
                            go(w, s, k, zs)
                        },
                        mode::Break => {
                            let mut ys = vec![(i, mode::Flat, x.clone())];
                            ys.push_all(rest);
                            if fitting(ys.clone(), w - k) {
                                go(w, s, k, ys)
                            } else {
                                let mut zs = vec![(i, mode::Break, x)];
                                zs.push_all(rest);
                                go(w, s, k, zs)
                            }
                        }
                    }
                }
            }
        }
    }
    go(w, s, 0, vec![(0, mode::Break, x)])
}

impl Doc {

    pub fn nil() -> Doc {
        Nil
    }

    pub fn append(self, e:Doc) -> Doc {
        match self {
            Nil => e,
            x => match e {
                Nil => x,
                y => Append(box x, box y)
            }
        }
    }

    pub fn nest(self, i:uint) -> Doc {
        Nest(i, box self)
    }

    pub fn text<S:Str>(s:S) -> Doc {
        Text(String::from_str(s.as_slice()))
    }

    pub fn brk(space:uint, offset:uint) -> Doc {
        Break(space, offset)
    }

    pub fn newline() -> Doc {
        Newline
    }

    pub fn group(self) -> Doc {
        Group(box self)
    }

    pub fn concat(ds:&[Doc]) -> Doc {
        ds.iter().fold(Nil, |a, b| a.append(b.clone()))
    }

    pub fn as_str<T:ToString>(t:T) -> Doc {
        Doc::text(t.to_string())
    }

    pub fn to_string(self, w:uint) -> String {
        let mut strs = best(w, Vec::new(), self);
        strs.reverse();
        strs.push(String::from_str("\n"));
        strs.concat()
    }
}
<commit_msg>Remove commented out code<commit_after>use super::mode;
use super::string_utils;

#[deriving(Clone)]
#[deriving(Show)]
enum DOC {
    Nil,
    Append(Box<Doc>, Box<Doc>),
    Break(uint, uint),
    Group(Box<Doc>),
    Nest(uint, Box<Doc>),
    Newline,
    Text(String),
}

pub type Doc = DOC;

fn fitting(xs:Vec<(uint,mode::Mode,Doc)>, left:uint) -> bool {
    match xs.as_slice() {
        [] => {
            true
        },
        [(i, mode, ref doc), rest..] => match doc.clone() {
            Nil => {
                fitting(rest.to_vec(), left)
            },
            Append(box x, box y) => {
                let mut ys = vec![(i, mode, x), (i, mode, y)];
                ys.push_all(rest);
                fitting(ys, left)
            },
            Nest(j, box x) => {
                let mut ys = vec![(i + j, mode, x)];
                ys.push_all(rest);
                fitting(ys, left)
            },
            Text(str) => {
                fitting(rest.to_vec(), left - str.len())
            },
            Break(sp, _) => match mode {
                mode::Flat => {
                    fitting(rest.to_vec(), left - sp)
                },
                mode::Break => {
                    true
                },
            },
            Newline => {
                true
            },
            Group(box x) => {
                let mut ys = vec![(i, mode, x)];
                ys.push_all(rest);
                fitting(ys, left)
            },
        }
    }
}

fn prepend<A:Clone>(mut v: Vec<A>, x:A) -> Vec<A> {
    v.insert(0, x);
    v
}

fn best(w:uint, s:Vec<String>, x:Doc) -> Vec<String> {
    fn go(w:uint, s:Vec<String>, k:uint, xs:Vec<(uint,mode::Mode,Doc)>) -> Vec<String> {
        match xs.as_slice() {
            [] => s,
            [(i, mode, ref doc), rest..] => match doc.clone() {
                Nil => {
                    go(w, s, k, rest.to_vec())
                },
                Append(box x, box y) => {
                    let mut zs = vec![(i, mode, x), (i, mode, y)];
                    zs.push_all(rest);
                    go(w, s, k, zs)
                },
                Nest(j, box x) => {
                    let mut zs = vec![(i + j, mode, x)];
                    zs.push_all(rest);
                    go(w, s, k, zs)
                },
                Text(str) => {
                    go(w, prepend(s, str.clone()), k + str.len(), rest.to_vec())
                },
                Newline => {
                    go(w, prepend(s, string_utils::nl_space(i)), i, rest.to_vec())
                },
                Break(sp, off) => {
                    match mode {
                        mode::Flat => {
                            go(w, prepend(s, string_utils::spaces(sp)), k + sp, rest.to_vec())
                        },
                        mode::Break => {
                            go(w, prepend(s, string_utils::nl_space(i + off)), i + off, rest.to_vec())
                        }
                    }
                },
                Group(box x) => {
                    match mode {
                        mode::Flat => {
                            let mut zs = vec![(i, mode::Flat, x)];
                            zs.push_all(rest);
                            go(w, s, k, zs)
                        },
                        mode::Break => {
                            let mut ys = vec![(i, mode::Flat, x.clone())];
                            ys.push_all(rest);
                            if fitting(ys.clone(), w - k) {
                                go(w, s, k, ys)
                            } else {
                                let mut zs = vec![(i, mode::Break, x)];
                                zs.push_all(rest);
                                go(w, s, k, zs)
                            }
                        }
                    }
                }
            }
        }
    }
    go(w, s, 0, vec![(0, mode::Break, x)])
}

impl Doc {

    pub fn nil() -> Doc {
        Nil
    }

    pub fn append(self, e:Doc) -> Doc {
        match self {
            Nil => e,
            x => match e {
                Nil => x,
                y => Append(box x, box y)
            }
        }
    }

    pub fn nest(self, i:uint) -> Doc {
        Nest(i, box self)
    }

    pub fn text<S:Str>(s:S) -> Doc {
        Text(String::from_str(s.as_slice()))
    }

    pub fn brk(space:uint, offset:uint) -> Doc {
        Break(space, offset)
    }

    pub fn newline() -> Doc {
        Newline
    }

    pub fn group(self) -> Doc {
        Group(box self)
    }

    pub fn concat(ds:&[Doc]) -> Doc {
        ds.iter().fold(Nil, |a, b| a.append(b.clone()))
    }

    pub fn as_str<T:ToString>(t:T) -> Doc {
        Doc::text(t.to_string())
    }

    pub fn to_string(self, w:uint) -> String {
        let mut strs = best(w, Vec::new(), self);
        strs.reverse();
        strs.push(String::from_str("\n"));
        strs.concat()
    }
}
<|endoftext|>