<commit_before>//! Glyph caching

use {rusttype, graphics, Texture, TextureSettings};
use std::collections::HashMap;
use graphics::types::Scalar;

extern crate fnv;
use self::fnv::FnvHasher;
use std::hash::BuildHasherDefault;

use std::path::Path;
use std::io::Read;
use std::fs::File;
use error::Error;

pub use graphics::types::FontSize;
use graphics::character::CharacterCache;

/// The type alias for font characters.
pub type Character<'a> = graphics::character::Character<'a, Texture>;

/// A struct used for caching rendered font.
pub struct GlyphCache<'a> {
    /// The font.
    pub font: rusttype::Font<'a>,
    // Maps from fontsize and character to offset, size and texture.
    data: HashMap<(FontSize, char),
                  ([Scalar; 2], [Scalar; 2], Texture),
                  BuildHasherDefault<FnvHasher>>,
}

impl<'a> GlyphCache<'a> {
    /// Constructor for a GlyphCache.
    pub fn new<P>(font: P) -> Result<GlyphCache<'static>, Error>
        where P: AsRef<Path>
    {
        let fnv = BuildHasherDefault::<FnvHasher>::default();
        let mut file = try!(File::open(font));
        let mut file_buffer = Vec::new();
        try!(file.read_to_end(&mut file_buffer));

        let collection = rusttype::FontCollection::from_bytes(file_buffer);
        let font = collection.into_font().unwrap();
        Ok(GlyphCache {
            font: font,
            data: HashMap::with_hasher(fnv),
        })
    }

    /// Creates a GlyphCache for a font stored in memory.
    pub fn from_bytes(font: &'a [u8]) -> Result<GlyphCache<'a>, Error> {
        let fnv = BuildHasherDefault::<FnvHasher>::default();
        let collection = rusttype::FontCollection::from_bytes(font);
        let font = collection.into_font().unwrap();
        Ok(GlyphCache {
            font: font,
            data: HashMap::with_hasher(fnv),
        })
    }

    /// Load all characters in the `chars` iterator for `size`
    pub fn preload_chars<I>(&mut self, size: FontSize, chars: I)
        where I: Iterator<Item = char>
    {
        for ch in chars {
            self.character(size, ch);
        }
    }

    /// Load all the printable ASCII characters for `size`. Includes space.
    pub fn preload_printable_ascii(&mut self, size: FontSize) {
        // [0x20, 0x7F) contains all printable ASCII characters ([' ', '~'])
        self.preload_chars(size, (0x20u8..0x7F).map(|ch| ch as char));
    }

    /// Return `ch` for `size` if it's already cached. Don't load.
    /// See the `preload_*` functions.
    pub fn opt_character(&self, size: FontSize, ch: char) -> Option<Character> {
        self.data.get(&(size, ch)).map(|&(offset, size, ref texture)| {
            Character {
                offset: offset,
                size: size,
                texture: texture,
            }
        })
    }
}

impl<'b> CharacterCache for GlyphCache<'b> {
    type Texture = Texture;

    fn character<'a>(
        &'a mut self,
        size: FontSize,
        ch: char
    ) -> Character<'a> {
        use std::collections::hash_map::Entry;
        use rusttype as rt;

        let size = ((size as f32) * 1.333).round() as u32 ; // convert points to pixels

        match self.data.entry((size, ch)) {
            //returning `into_mut()' to get reference with 'a lifetime
            Entry::Occupied(v) => {
                let &mut (offset, size, ref texture) = v.into_mut();
                Character {
                    offset: offset,
                    size: size,
                    texture: texture
                }
            }
            Entry::Vacant(v) => {
                let glyph = self.font.glyph(ch).unwrap(); // this is only None for invalid GlyphIds, but char is converted to a Codepoint which must result in a glyph.
                let scale = rt::Scale::uniform(size as f32);
                let mut glyph = glyph.scaled(scale);

                // some fonts do not contain glyph zero as fallback, instead try U+FFFD.
                if glyph.id() == rt::GlyphId(0) && glyph.shape().is_none() {
                    glyph = self.font.glyph('\u{FFFD}').unwrap().scaled(scale);
                }

                let h_metrics = glyph.h_metrics();
                let bounding_box = glyph.exact_bounding_box().unwrap_or(rt::Rect{min: rt::Point{x: 0.0, y: 0.0}, max: rt::Point{x: 0.0, y: 0.0} });
                let glyph = glyph.positioned(rt::point(0.0, 0.0));
                let pixel_bounding_box = glyph.pixel_bounding_box().unwrap_or(rt::Rect{min: rt::Point{x: 0, y: 0}, max: rt::Point{x: 0, y: 0} });
                let pixel_bb_width = pixel_bounding_box.width() + 2;
                let pixel_bb_height = pixel_bounding_box.height() + 2;

                let mut image_buffer = Vec::<u8>::new();
                image_buffer.resize((pixel_bb_width * pixel_bb_height) as usize, 0);
                glyph.draw(|x, y, v| {
                   let pos = ((x+1) + (y+1) * (pixel_bb_width as u32)) as usize;
                   image_buffer[pos] = (255.0 * v) as u8;
                });

                let &mut (offset, size, ref texture) = v.insert((
                    [
                        bounding_box.min.x as Scalar - 1.0,
                        -pixel_bounding_box.min.y as Scalar + 1.0,
                    ],
                    [
                        h_metrics.advance_width as Scalar,
                        0 as Scalar,
                    ],
                    {
                        if pixel_bb_width == 0 || pixel_bb_height == 0 {
                            Texture::empty().unwrap()
                        } else {
                            Texture::from_memory_alpha(
                                &image_buffer,
                                pixel_bb_width as u32,
                                pixel_bb_height as u32,
                                &TextureSettings::new()
                            ).unwrap()
                        }
                    },
                ));
                Character {
                    offset: offset,
                    size: size,
                    texture: texture
                }
            }
        }
    }
}
<commit_msg>Add GlyphCache::from_font constructor<commit_after>//! Glyph caching

use {rusttype, graphics, Texture, TextureSettings};
use std::collections::HashMap;
use graphics::types::Scalar;

extern crate fnv;
use self::fnv::FnvHasher;
use std::hash::BuildHasherDefault;

use std::path::Path;
use std::io::Read;
use std::fs::File;
use error::Error;

pub use graphics::types::FontSize;
use graphics::character::CharacterCache;

/// The type alias for font characters.
pub type Character<'a> = graphics::character::Character<'a, Texture>;

/// A struct used for caching rendered font.
pub struct GlyphCache<'a> {
    /// The font.
    pub font: rusttype::Font<'a>,
    // Maps from fontsize and character to offset, size and texture.
    data: HashMap<(FontSize, char),
                  ([Scalar; 2], [Scalar; 2], Texture),
                  BuildHasherDefault<FnvHasher>>,
}

impl<'a> GlyphCache<'a> {
    /// Constructs a GlyphCache from a Font.
    pub fn from_font(font: rusttype::Font<'a>) -> Self {
        let fnv = BuildHasherDefault::<FnvHasher>::default();
        GlyphCache {
            font: font,
            data: HashMap::with_hasher(fnv),
        }
    }

    /// Constructor for a GlyphCache.
    pub fn new<P>(font: P) -> Result<GlyphCache<'static>, Error>
        where P: AsRef<Path>
    {
        let fnv = BuildHasherDefault::<FnvHasher>::default();
        let mut file = try!(File::open(font));
        let mut file_buffer = Vec::new();
        try!(file.read_to_end(&mut file_buffer));

        let collection = rusttype::FontCollection::from_bytes(file_buffer);
        let font = collection.into_font().unwrap();
        Ok(GlyphCache {
            font: font,
            data: HashMap::with_hasher(fnv),
        })
    }

    /// Creates a GlyphCache for a font stored in memory.
    pub fn from_bytes(font: &'a [u8]) -> Result<GlyphCache<'a>, Error> {
        let collection = rusttype::FontCollection::from_bytes(font);
        let font = collection.into_font().unwrap();
        Ok(Self::from_font(font))
    }

    /// Load all characters in the `chars` iterator for `size`
    pub fn preload_chars<I>(&mut self, size: FontSize, chars: I)
        where I: Iterator<Item = char>
    {
        for ch in chars {
            self.character(size, ch);
        }
    }

    /// Load all the printable ASCII characters for `size`. Includes space.
    pub fn preload_printable_ascii(&mut self, size: FontSize) {
        // [0x20, 0x7F) contains all printable ASCII characters ([' ', '~'])
        self.preload_chars(size, (0x20u8..0x7F).map(|ch| ch as char));
    }

    /// Return `ch` for `size` if it's already cached. Don't load.
    /// See the `preload_*` functions.
    pub fn opt_character(&self, size: FontSize, ch: char) -> Option<Character> {
        self.data.get(&(size, ch)).map(|&(offset, size, ref texture)| {
            Character {
                offset: offset,
                size: size,
                texture: texture,
            }
        })
    }
}

impl<'b> CharacterCache for GlyphCache<'b> {
    type Texture = Texture;

    fn character<'a>(
        &'a mut self,
        size: FontSize,
        ch: char
    ) -> Character<'a> {
        use std::collections::hash_map::Entry;
        use rusttype as rt;

        let size = ((size as f32) * 1.333).round() as u32 ; // convert points to pixels

        match self.data.entry((size, ch)) {
            //returning `into_mut()' to get reference with 'a lifetime
            Entry::Occupied(v) => {
                let &mut (offset, size, ref texture) = v.into_mut();
                Character {
                    offset: offset,
                    size: size,
                    texture: texture
                }
            }
            Entry::Vacant(v) => {
                let glyph = self.font.glyph(ch).unwrap(); // this is only None for invalid GlyphIds, but char is converted to a Codepoint which must result in a glyph.
                let scale = rt::Scale::uniform(size as f32);
                let mut glyph = glyph.scaled(scale);

                // some fonts do not contain glyph zero as fallback, instead try U+FFFD.
                if glyph.id() == rt::GlyphId(0) && glyph.shape().is_none() {
                    glyph = self.font.glyph('\u{FFFD}').unwrap().scaled(scale);
                }

                let h_metrics = glyph.h_metrics();
                let bounding_box = glyph.exact_bounding_box().unwrap_or(rt::Rect{min: rt::Point{x: 0.0, y: 0.0}, max: rt::Point{x: 0.0, y: 0.0} });
                let glyph = glyph.positioned(rt::point(0.0, 0.0));
                let pixel_bounding_box = glyph.pixel_bounding_box().unwrap_or(rt::Rect{min: rt::Point{x: 0, y: 0}, max: rt::Point{x: 0, y: 0} });
                let pixel_bb_width = pixel_bounding_box.width() + 2;
                let pixel_bb_height = pixel_bounding_box.height() + 2;

                let mut image_buffer = Vec::<u8>::new();
                image_buffer.resize((pixel_bb_width * pixel_bb_height) as usize, 0);
                glyph.draw(|x, y, v| {
                   let pos = ((x+1) + (y+1) * (pixel_bb_width as u32)) as usize;
                   image_buffer[pos] = (255.0 * v) as u8;
                });

                let &mut (offset, size, ref texture) = v.insert((
                    [
                        bounding_box.min.x as Scalar - 1.0,
                        -pixel_bounding_box.min.y as Scalar + 1.0,
                    ],
                    [
                        h_metrics.advance_width as Scalar,
                        0 as Scalar,
                    ],
                    {
                        if pixel_bb_width == 0 || pixel_bb_height == 0 {
                            Texture::empty().unwrap()
                        } else {
                            Texture::from_memory_alpha(
                                &image_buffer,
                                pixel_bb_width as u32,
                                pixel_bb_height as u32,
                                &TextureSettings::new()
                            ).unwrap()
                        }
                    },
                ));
                Character {
                    offset: offset,
                    size: size,
                    texture: texture
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use ast::{Expr, Operator};

#[derive(Debug, PartialEq)]
pub enum Value {
    Nil,
    Boolean(bool),
    Number(f64),
    // TODO: Don't copy strings, intern them
    String(String),
}

impl Value {
    pub fn is_truthy(&self) -> bool {
        match *self {
            Value::Nil | Value::Boolean(false) => false,
            _ => true,
        }
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Value::Nil => write!(f, "nil"),
            Value::Boolean(val) => write!(f, "{}", val),
            Value::Number(val) => write!(f, "{}", val),
            Value::String(ref val) => write!(f, "{}", val),
        }
    }
}

pub trait Evaluate {
    fn eval(&self) -> Result<Value, String>;
}

impl Evaluate for Expr {
    fn eval(&self) -> Result<Value, String> {
        match *self {
            Expr::Nil => Ok(Value::Nil),
            Expr::BooleanLiteral(val) => Ok(Value::Boolean(val)),
            Expr::NumberLiteral(val) => Ok(Value::Number(val)),
            Expr::StringLiteral(ref val) => Ok(Value::String(val.clone())),

            Expr::Identifier(_) => unimplemented!(),

            Expr::UnaryOp(ref op, ref expr) => {
                let expr_val = expr.eval()?;

                match *op {
                    Operator::Not => Ok(Value::Boolean(!expr_val.is_truthy())),

                    Operator::UnaryMinus => match expr_val {
                        Value::Number(val) => Ok(Value::Number(-val)),
                        other => Err(format!("{} cannot be negated", other)),
                    },

                    ref other => Err(format!("{:?} is not a valid unary operator", other)),
                }
            }

            Expr::BinaryOp(ref op, ref left, ref right) => {
                let left_val = left.eval()?;
                let right_val = right.eval()?;

                match *op {
                    // Arithmatic
                    Operator::Add => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l + r)),
                        (Value::String(l), Value::String(r)) => Ok(Value::String(l + &r)),
                        (l, r) => Err(format!("{} and {} cannot be added", l, r)),
                    },

                    Operator::Subtract => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l - r)),
                        (l, r) => Err(format!("{} and {} cannot be subtracted", l, r)),
                    },

                    Operator::Multiply => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l * r)),
                        (l, r) => Err(format!("{} and {} cannot be multiplied", l, r)),
                    },

                    Operator::Divide => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l / r)),
                        (l, r) => Err(format!("{} and {} cannot be added", l, r)),
                    },

                    // Comparison
                    Operator::Equals => Ok(Value::Boolean(left_val == right_val)),
                    Operator::NotEquals => Ok(Value::Boolean(left_val != right_val)),

                    Operator::GreaterThan => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Boolean(l > r)),
                        (l, r) => Err(format!("{} and {} cannot be compared", l, r)),
                    },

                    Operator::GreaterEquals => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Boolean(l >= r)),
                        (l, r) => Err(format!("{} and {} cannot be compared", l, r)),
                    },

                    Operator::LessThan => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Boolean(l < r)),
                        (l, r) => Err(format!("{} and {} cannot be compared", l, r)),
                    },

                    Operator::LessEquals => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Boolean(l >= r)),
                        (l, r) => Err(format!("{} and {} cannot be compared", l, r)),
                    },

                    ref other => Err(format!("{:?} is not a valid binary operator", other)),
                }
            }
        }
    }
}
<commit_msg>Fix <= being treated as a >=<commit_after>use std::fmt;
use ast::{Expr, Operator};

#[derive(Debug, PartialEq)]
pub enum Value {
    Nil,
    Boolean(bool),
    Number(f64),
    // TODO: Don't copy strings, intern them
    String(String),
}

impl Value {
    pub fn is_truthy(&self) -> bool {
        match *self {
            Value::Nil | Value::Boolean(false) => false,
            _ => true,
        }
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Value::Nil => write!(f, "nil"),
            Value::Boolean(val) => write!(f, "{}", val),
            Value::Number(val) => write!(f, "{}", val),
            Value::String(ref val) => write!(f, "{}", val),
        }
    }
}

pub trait Evaluate {
    fn eval(&self) -> Result<Value, String>;
}

impl Evaluate for Expr {
    fn eval(&self) -> Result<Value, String> {
        match *self {
            Expr::Nil => Ok(Value::Nil),
            Expr::BooleanLiteral(val) => Ok(Value::Boolean(val)),
            Expr::NumberLiteral(val) => Ok(Value::Number(val)),
            Expr::StringLiteral(ref val) => Ok(Value::String(val.clone())),

            Expr::Identifier(_) => unimplemented!(),

            Expr::UnaryOp(ref op, ref expr) => {
                let expr_val = expr.eval()?;

                match *op {
                    Operator::Not => Ok(Value::Boolean(!expr_val.is_truthy())),

                    Operator::UnaryMinus => match expr_val {
                        Value::Number(val) => Ok(Value::Number(-val)),
                        other => Err(format!("{} cannot be negated", other)),
                    },

                    ref other => Err(format!("{:?} is not a valid unary operator", other)),
                }
            }

            Expr::BinaryOp(ref op, ref left, ref right) => {
                let left_val = left.eval()?;
                let right_val = right.eval()?;

                match *op {
                    // Arithmatic
                    Operator::Add => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l + r)),
                        (Value::String(l), Value::String(r)) => Ok(Value::String(l + &r)),
                        (l, r) => Err(format!("{} and {} cannot be added", l, r)),
                    },

                    Operator::Subtract => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l - r)),
                        (l, r) => Err(format!("{} and {} cannot be subtracted", l, r)),
                    },

                    Operator::Multiply => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l * r)),
                        (l, r) => Err(format!("{} and {} cannot be multiplied", l, r)),
                    },

                    Operator::Divide => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l / r)),
                        (l, r) => Err(format!("{} and {} cannot be added", l, r)),
                    },

                    // Comparison
                    Operator::Equals => Ok(Value::Boolean(left_val == right_val)),
                    Operator::NotEquals => Ok(Value::Boolean(left_val != right_val)),

                    Operator::GreaterThan => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Boolean(l > r)),
                        (l, r) => Err(format!("{} and {} cannot be compared", l, r)),
                    },

                    Operator::GreaterEquals => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Boolean(l >= r)),
                        (l, r) => Err(format!("{} and {} cannot be compared", l, r)),
                    },

                    Operator::LessThan => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Boolean(l < r)),
                        (l, r) => Err(format!("{} and {} cannot be compared", l, r)),
                    },

                    Operator::LessEquals => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Boolean(l <= r)),
                        (l, r) => Err(format!("{} and {} cannot be compared", l, r)),
                    },

                    ref other => Err(format!("{:?} is not a valid binary operator", other)),
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use collections::HashMap;
use collections::hashmap;
use std::default::Default;
use std::slice;
use core::wire_format;

pub enum UnknownValue {
    UnknownFixed32(u32),
    UnknownFixed64(u64),
    UnknownVarint(u64),
    UnknownLengthDelimited(~[u8]),
}

impl UnknownValue {
    pub fn wire_type(&self) -> wire_format::WireType {
        self.get_ref().wire_type()
    }

    pub fn get_ref<'s>(&'s self) -> UnknownValueRef<'s> {
        match *self {
            UnknownFixed32(fixed32) => UnknownFixed32Ref(fixed32),
            UnknownFixed64(fixed64) => UnknownFixed64Ref(fixed64),
            UnknownVarint(varint) => UnknownVarintRef(varint),
            UnknownLengthDelimited(ref bytes) => UnknownLengthDelimitedRef(bytes.as_slice()),
        }
    }
}

pub enum UnknownValueRef<'o> {
    UnknownFixed32Ref(u32),
    UnknownFixed64Ref(u64),
    UnknownVarintRef(u64),
    UnknownLengthDelimitedRef(&'o [u8]),
}

impl<'o> UnknownValueRef<'o> {
    pub fn wire_type(&self) -> wire_format::WireType {
        match *self {
            UnknownFixed32Ref(_) => wire_format::WireTypeFixed32,
            UnknownFixed64Ref(_) => wire_format::WireTypeFixed64,
            UnknownVarintRef(_) => wire_format::WireTypeVarint,
            UnknownLengthDelimitedRef(_) => wire_format::WireTypeLengthDelimited,
        }
    }
}

#[deriving(Clone,Eq,Default)]
pub struct UnknownValues {
    pub fixed32: Vec<u32>,
    pub fixed64: Vec<u64>,
    pub varint: Vec<u64>,
    pub length_delimited: Vec<~[u8]>,
}

impl UnknownValues {
    pub fn add_value(&mut self, value: UnknownValue) {
        match value {
            UnknownFixed64(fixed64) => self.fixed64.push(fixed64),
            UnknownFixed32(fixed32) => self.fixed32.push(fixed32),
            UnknownVarint(varint) => self.varint.push(varint),
            UnknownLengthDelimited(length_delimited) => self.length_delimited.push(length_delimited),
        };
    }

    pub fn iter<'s>(&'s self) -> UnknownValuesIter<'s> {
        UnknownValuesIter {
            fixed32: self.fixed32.iter(),
            fixed64: self.fixed64.iter(),
            varint: self.varint.iter(),
            length_delimited: self.length_delimited.iter(),
        }
    }
}

pub struct UnknownValuesIter<'o> {
    fixed32: slice::Items<'o, u32>,
    fixed64: slice::Items<'o, u64>,
    varint: slice::Items<'o, u64>,
    length_delimited: slice::Items<'o, ~[u8]>,
}

impl<'o> Iterator<UnknownValueRef<'o>> for UnknownValuesIter<'o> {
    fn next(&mut self) -> Option<UnknownValueRef<'o>> {
        let fixed32 = self.fixed32.next();
        if fixed32.is_some() {
            return Some(UnknownFixed32Ref(*fixed32.unwrap()));
        }
        let fixed64 = self.fixed64.next();
        if fixed64.is_some() {
            return Some(UnknownFixed64Ref(*fixed64.unwrap()));
        }
        let varint = self.varint.next();
        if varint.is_some() {
            return Some(UnknownVarintRef(*varint.unwrap()));
        }
        let length_delimited = self.length_delimited.next();
        if length_delimited.is_some() {
            return Some(UnknownLengthDelimitedRef(length_delimited.get_ref().as_slice()))
        }
        None
    }
}

#[deriving(Clone,Eq,Default)]
pub struct UnknownFields {
    // option is needed, so it could be placed in static field
    pub fields: Option<HashMap<u32, UnknownValues>>,
}

impl UnknownFields {
    pub fn default_instance() -> &'static UnknownFields {
        static instance: UnknownFields = UnknownFields {
            fields: None,
        };
        &'static instance
    }

    fn init_map(&mut self) {
        if self.fields.is_none() {
            self.fields = Some(Default::default());
        }
    }

    fn find_field<'a>(&'a mut self, number: u32) -> &'a mut UnknownValues {
        self.init_map();

        if !self.fields.get_ref().contains_key(&number) {
            self.fields.get_mut_ref().insert(number, Default::default());
        }

        self.fields.get_mut_ref().find_mut(&number).unwrap()
    }

    pub fn add_fixed32(&mut self, number: u32, fixed32: u32) {
        self.find_field(number).fixed32.push(fixed32);
    }

    pub fn add_fixed64(&mut self, number: u32, fixed64: u64) {
        self.find_field(number).fixed64.push(fixed64);
    }

    pub fn add_varint(&mut self, number: u32, varint: u64) {
        self.find_field(number).varint.push(varint);
    }

    pub fn add_length_delimited(&mut self, number: u32, length_delimited: ~[u8]) {
        self.find_field(number).length_delimited.push(length_delimited);
    }

    pub fn add_value(&mut self, number: u32, value: UnknownValue) {
        self.find_field(number).add_value(value);
    }

    pub fn iter<'s>(&'s self) -> UnknownFieldIter<'s> {
        UnknownFieldIter {
            entries: self.fields.as_ref().map(|m| m.iter())
        }
    }
}

pub struct UnknownFieldIter<'s> {
    entries: Option<hashmap::Entries<'s, u32, UnknownValues>>,
}

impl<'s> Iterator<(u32, &'s UnknownValues)> for UnknownFieldIter<'s> {
    fn next(&mut self) -> Option<(u32, &'s UnknownValues)> {
        if self.entries.is_none() {
            None
        } else {
            self.entries.get_mut_ref().next().map(|(&number, values)| (number, values))
        }
    }
}
<commit_msg>Use HashMap shortcut<commit_after>use collections::HashMap;
use collections::hashmap;
use std::default::Default;
use std::slice;
use core::wire_format;

pub enum UnknownValue {
    UnknownFixed32(u32),
    UnknownFixed64(u64),
    UnknownVarint(u64),
    UnknownLengthDelimited(~[u8]),
}

impl UnknownValue {
    pub fn wire_type(&self) -> wire_format::WireType {
        self.get_ref().wire_type()
    }

    pub fn get_ref<'s>(&'s self) -> UnknownValueRef<'s> {
        match *self {
            UnknownFixed32(fixed32) => UnknownFixed32Ref(fixed32),
            UnknownFixed64(fixed64) => UnknownFixed64Ref(fixed64),
            UnknownVarint(varint) => UnknownVarintRef(varint),
            UnknownLengthDelimited(ref bytes) => UnknownLengthDelimitedRef(bytes.as_slice()),
        }
    }
}

pub enum UnknownValueRef<'o> {
    UnknownFixed32Ref(u32),
    UnknownFixed64Ref(u64),
    UnknownVarintRef(u64),
    UnknownLengthDelimitedRef(&'o [u8]),
}

impl<'o> UnknownValueRef<'o> {
    pub fn wire_type(&self) -> wire_format::WireType {
        match *self {
            UnknownFixed32Ref(_) => wire_format::WireTypeFixed32,
            UnknownFixed64Ref(_) => wire_format::WireTypeFixed64,
            UnknownVarintRef(_) => wire_format::WireTypeVarint,
            UnknownLengthDelimitedRef(_) => wire_format::WireTypeLengthDelimited,
        }
    }
}

#[deriving(Clone,Eq,Default)]
pub struct UnknownValues {
    pub fixed32: Vec<u32>,
    pub fixed64: Vec<u64>,
    pub varint: Vec<u64>,
    pub length_delimited: Vec<~[u8]>,
}

impl UnknownValues {
    pub fn add_value(&mut self, value: UnknownValue) {
        match value {
            UnknownFixed64(fixed64) => self.fixed64.push(fixed64),
            UnknownFixed32(fixed32) => self.fixed32.push(fixed32),
            UnknownVarint(varint) => self.varint.push(varint),
            UnknownLengthDelimited(length_delimited) => self.length_delimited.push(length_delimited),
        };
    }

    pub fn iter<'s>(&'s self) -> UnknownValuesIter<'s> {
        UnknownValuesIter {
            fixed32: self.fixed32.iter(),
            fixed64: self.fixed64.iter(),
            varint: self.varint.iter(),
            length_delimited: self.length_delimited.iter(),
        }
    }
}

pub struct UnknownValuesIter<'o> {
    fixed32: slice::Items<'o, u32>,
    fixed64: slice::Items<'o, u64>,
    varint: slice::Items<'o, u64>,
    length_delimited: slice::Items<'o, ~[u8]>,
}

impl<'o> Iterator<UnknownValueRef<'o>> for UnknownValuesIter<'o> {
    fn next(&mut self) -> Option<UnknownValueRef<'o>> {
        let fixed32 = self.fixed32.next();
        if fixed32.is_some() {
            return Some(UnknownFixed32Ref(*fixed32.unwrap()));
        }
        let fixed64 = self.fixed64.next();
        if fixed64.is_some() {
            return Some(UnknownFixed64Ref(*fixed64.unwrap()));
        }
        let varint = self.varint.next();
        if varint.is_some() {
            return Some(UnknownVarintRef(*varint.unwrap()));
        }
        let length_delimited = self.length_delimited.next();
        if length_delimited.is_some() {
            return Some(UnknownLengthDelimitedRef(length_delimited.get_ref().as_slice()))
        }
        None
    }
}

#[deriving(Clone,Eq,Default)]
pub struct UnknownFields {
    // option is needed, so it could be placed in static field
    pub fields: Option<HashMap<u32, UnknownValues>>,
}

impl UnknownFields {
    pub fn default_instance() -> &'static UnknownFields {
        static instance: UnknownFields = UnknownFields {
            fields: None,
        };
        &'static instance
    }

    fn init_map(&mut self) {
        if self.fields.is_none() {
            self.fields = Some(Default::default());
        }
    }

    fn find_field<'a>(&'a mut self, number: u32) -> &'a mut UnknownValues {
        self.init_map();

        self.fields.get_mut_ref()
            .find_or_insert_with(number, |_| Default::default())
    }

    pub fn add_fixed32(&mut self, number: u32, fixed32: u32) {
        self.find_field(number).fixed32.push(fixed32);
    }

    pub fn add_fixed64(&mut self, number: u32, fixed64: u64) {
        self.find_field(number).fixed64.push(fixed64);
    }

    pub fn add_varint(&mut self, number: u32, varint: u64) {
        self.find_field(number).varint.push(varint);
    }

    pub fn add_length_delimited(&mut self, number: u32, length_delimited: ~[u8]) {
        self.find_field(number).length_delimited.push(length_delimited);
    }

    pub fn add_value(&mut self, number: u32, value: UnknownValue) {
        self.find_field(number).add_value(value);
    }

    pub fn iter<'s>(&'s self) -> UnknownFieldIter<'s> {
        UnknownFieldIter {
            entries: self.fields.as_ref().map(|m| m.iter())
        }
    }
}

pub struct UnknownFieldIter<'s> {
    entries: Option<hashmap::Entries<'s, u32, UnknownValues>>,
}

impl<'s> Iterator<(u32, &'s UnknownValues)> for UnknownFieldIter<'s> {
    fn next(&mut self) -> Option<(u32, &'s UnknownValues)> {
        if self.entries.is_none() {
            None
        } else {
            self.entries.get_mut_ref().next().map(|(&number, values)| (number, values))
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

pub use self::builder::MessageBuilder;

mod builder;

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Message {
    uuid: String,
    name: Option<String>,
    values: BTreeMap<String, String>
}

impl Message {
    pub fn uuid(&self) -> &String {
        &self.uuid
    }

    pub fn name(&self) -> Option<&String> {
        self.name.as_ref()
    }

    pub fn get(&self, key: &str) -> Option<&String> {
        self.values.get(key)
    }

    pub fn insert(&mut self, key: &str, value: &str) {
        self.values.insert(key.to_string(), value.to_string());
    }
}
<commit_msg>Message: add values() method<commit_after>use std::collections::BTreeMap;

pub use self::builder::MessageBuilder;

mod builder;

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Message {
    uuid: String,
    name: Option<String>,
    values: BTreeMap<String, String>
}

impl Message {
    pub fn uuid(&self) -> &String {
        &self.uuid
    }

    pub fn name(&self) -> Option<&String> {
        self.name.as_ref()
    }

    pub fn get(&self, key: &str) -> Option<&String> {
        self.values.get(key)
    }

    pub fn values(&self) -> &BTreeMap<String, String> {
        &self.values
    }

    pub fn insert(&mut self, key: &str, value: &str) {
        self.values.insert(key.to_string(), value.to_string());
    }
}
<|endoftext|>


<commit_before>use runtime::RuntimeFn;

mod fs;

/// A descriptor struct for a loadable module.
pub enum Module {
    /// Entry point for a native runtime module.
    Native(ModuleTable),

    /// A plain Lua module that is built-in.
    Builtin(&'static str),
}

/// An entrypoint table for a native module.
pub struct ModuleTable(pub &'static [(&'static str, RuntimeFn)]);

/// Fetches a built-in Lua module by the given module's name.
///
/// Returns an `Option<Module>` containing the Lua source or MTABLE of the given module, or `None`
/// if the module is not defined.
///
/// The list of available built-in modules is determined at compile-time and modules embedded into
/// the Rote binary itself.
pub fn fetch(name: &str) -> Option<Module> {
    match name {
        // Statically include and match the built-in modules.
        "core"      => Some(Module::Builtin(include_str!("core.lua"))),
        "cargo"     => Some(Module::Builtin(include_str!("cargo.lua"))),
        "cpp"       => Some(Module::Builtin(include_str!("cpp.lua"))),
        "docker"    => Some(Module::Builtin(include_str!("docker.lua"))),
        "fs"        => Some(Module::Native(fs::MTABLE)),
        "git"       => Some(Module::Builtin(include_str!("git.lua"))),
        "java"      => Some(Module::Builtin(include_str!("java.lua"))),
        "php"       => Some(Module::Builtin(include_str!("php.lua"))),
        "table"     => Some(Module::Builtin(include_str!("table.lua"))),
        // If you want to add a built-in module, add your module name and file here.
        _ => None
    }
}
<commit_msg>Switch to native pkg module<commit_after>use runtime::RuntimeFn;

mod fs;
mod pkg;

/// A descriptor struct for a loadable module.
pub enum Module {
    /// Entry point for a native runtime module.
    Native(ModuleTable),

    /// A plain Lua module that is built-in.
    Builtin(&'static str),
}

/// An entrypoint table for a native module.
pub struct ModuleTable(pub &'static [(&'static str, RuntimeFn)]);

/// Fetches a built-in Lua module by the given module's name.
///
/// Returns an `Option<Module>` containing the Lua source or MTABLE of the given module, or `None`
/// if the module is not defined.
///
/// The list of available built-in modules is determined at compile-time and modules embedded into
/// the Rote binary itself.
pub fn fetch(name: &str) -> Option<Module> {
    match name {
        // Statically include and match the built-in modules.
        "core"      => Some(Module::Builtin(include_str!("core.lua"))),
        "cargo"     => Some(Module::Builtin(include_str!("cargo.lua"))),
        "cpp"       => Some(Module::Builtin(include_str!("cpp.lua"))),
        "docker"    => Some(Module::Builtin(include_str!("docker.lua"))),
        "fs"        => Some(Module::Native(fs::MTABLE)),
        "git"       => Some(Module::Builtin(include_str!("git.lua"))),
        "java"      => Some(Module::Builtin(include_str!("java.lua"))),
        "pkg"       => Some(Module::Native(pkg::MTABLE)),
        "php"       => Some(Module::Builtin(include_str!("php.lua"))),
        "table"     => Some(Module::Builtin(include_str!("table.lua"))),
        // If you want to add a built-in module, add your module name and file here.
        _ => None
    }
}
<|endoftext|>


<commit_before>use address::{LENGTH, Address, Addressable};
use num::bigint::{BigUint, ToBigUint};
use std::collections::HashMap;
use num;

struct NodeBucket<A: Addressable> {
    k: usize,
    min_exp: usize,
    max_exp: usize,
    addresses: Vec<Address>,
    nodes: HashMap<Address, A>
}

impl<A: Addressable> NodeBucket<A> {
    pub fn new(k: usize) -> NodeBucket<A> {
        let min_exp = 0;
        let max_exp = LENGTH;
        NodeBucket {
            k: k,
            min_exp: min_exp,
            max_exp: max_exp,
            addresses: Vec::with_capacity(k),
            nodes: HashMap::with_capacity(k)
        }
    }

    pub fn contains(&self, address: &Address) -> bool {
        self.addresses.contains(address)
    }

    pub fn covers(&self, address: &Address) -> bool {
        let numeric = address.as_numeric();
        numeric >= self.min() && numeric <= self.max()
    }

    fn max(&self) -> num::BigUint {
        num::pow(2u8.to_biguint().unwrap(), self.max_exp) - 1.to_biguint().unwrap()
    }

    fn min(&self) -> num::BigUint {
        num::pow(2.to_biguint().unwrap(), self.min_exp) - 1.to_biguint().unwrap()
    }

    pub fn insert(&mut self, node: A) {
        let address = node.address();
        if let Some(pos) = self.addresses.iter().position(|&a| a == address) {
            self.addresses.remove(pos);
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        } else if !self.is_full() {
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        }
    }

    pub fn is_full(&self) -> bool {
        self.addresses.len() >= self.k
    }

    pub fn split(&mut self) -> (Self, Self) {
        let partition = num::pow(2.to_biguint().unwrap(), self.max_exp - 1);
        let addresses = self.addresses.clone();
        let (a_addresses, b_addresses): (Vec<Address>, Vec<Address>) = addresses
            .into_iter()
            .partition(|&a| a.as_numeric() < partition);
        let mut a_nodes = HashMap::new();
        let mut b_nodes = HashMap::new();
        for (address, node) in self.nodes.drain() {
            if address.as_numeric() < partition {
                a_nodes.insert(address, node);
            } else {
                b_nodes.insert(address, node);
            }
        }

        let a = NodeBucket {
            k: self.k,
            min_exp: 0,
            max_exp: self.max_exp - 1,
            addresses: a_addresses,
            nodes: a_nodes
        };
        let b = NodeBucket {
            k: self.k,
            min_exp: self.max_exp - 1,
            max_exp: LENGTH,
            addresses: b_addresses,
            nodes: b_nodes
        };
        (a, b)
    }
}

#[cfg(test)]
mod tests {
    use address::{Address, Addressable};
    use super::NodeBucket;

    #[derive(Clone,Copy,Debug,PartialEq,Eq)]
    struct Node {
        pub address: Address
    }

    impl Node {
        fn new(address: Address) -> Node {
            Node { address: address }
        }
    }

    impl Addressable for Node {
        fn address(&self) -> Address {
            self.address
        }
    }

    #[test]
    fn test_insert() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        let node = Node::new(Address::for_content("some string"));
        bucket.insert(node);
        assert_eq!(bucket.addresses.len(), 1);
    }

    #[test]
    fn test_insert_duplicate() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        let a = Node::new(Address::for_content("node 1"));
        let b = Node::new(Address::for_content("node 2"));
        let c = Node::new(Address::for_content("node 1"));

        bucket.insert(a.clone());
        bucket.insert(b);
        bucket.insert(c);

        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes[&Address::for_content("node 1")], a);
    }

    #[test]
    fn test_insert_full() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(2);
        bucket.insert(Node::new(Address::for_content("node 1")));
        bucket.insert(Node::new(Address::for_content("node 2")));
        bucket.insert(Node::new(Address::for_content("node 3")));
        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes.get(&Address::for_content("node 3")), None);
    }

    #[test]
    fn test_is_full() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(2);
        assert!(!bucket.is_full());

        bucket.insert(Node::new(Address::for_content("node 1")));
        bucket.insert(Node::new(Address::for_content("node 2")));
        assert!(bucket.is_full());
    }

    #[test]
    fn test_contains() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        bucket.insert(Node::new(Address::for_content("node 1")));
        assert!(bucket.contains(&Address::for_content("node 1")));
    }

    #[test]
    fn test_covers() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        let address_1 = Address::from_str("0000000000000000000000000000000000000000");
        let address_2 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        assert!(bucket.covers(&address_1));
        assert!(bucket.covers(&address_2));
    }

    #[test]
    fn test_split() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(2);
        let node_1 = Node::new(Address::from_str("0000000000000000000000000000000000000000"));
        let node_2 = Node::new(Address::from_str("ffffffffffffffffffffffffffffffffffffffff"));
        bucket.insert(node_1);
        bucket.insert(node_2);
        let (a, b) = bucket.split();
        assert_eq!(a.addresses.len(), 1);
        assert_eq!(b.addresses.len(), 1);
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")], node_1);
        assert_eq!(b.nodes[&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")], node_2);
        assert!(a.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(!a.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
        assert!(!b.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(b.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
    }
}
<commit_msg>Use biguint ranges and division by 2 instead of exponents<commit_after>use address::{LENGTH, Address, Addressable};
use num::bigint::{BigUint, ToBigUint};
use std::collections::HashMap;
use num;

struct NodeBucket<A: Addressable> {
    k: usize,
    min: BigUint,
    max: BigUint,
    addresses: Vec<Address>,
    nodes: HashMap<Address, A>
}

impl<A: Addressable> NodeBucket<A> {
    pub fn new(k: usize) -> NodeBucket<A> {
        let min = 0.to_biguint().unwrap();
        let max = num::pow(2.to_biguint().unwrap(), LENGTH);
        NodeBucket {
            k: k,
            min: min,
            max: max,
            addresses: Vec::with_capacity(k),
            nodes: HashMap::with_capacity(k)
        }
    }

    pub fn contains(&self, address: &Address) -> bool {
        self.addresses.contains(address)
    }

    pub fn covers(&self, address: &Address) -> bool {
        let numeric = address.as_numeric();
        self.min <= numeric && numeric < self.max
    }

    pub fn insert(&mut self, node: A) {
        let address = node.address();
        if let Some(pos) = self.addresses.iter().position(|&a| a == address) {
            self.addresses.remove(pos);
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        } else if !self.is_full() {
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        }
    }

    pub fn is_full(&self) -> bool {
        self.addresses.len() >= self.k
    }

    pub fn split(&mut self) -> (Self, Self) {
        let partition = self.max.clone() / 2.to_biguint().unwrap();
        let addresses = self.addresses.clone();
        let (a_addresses, b_addresses): (Vec<Address>, Vec<Address>) = addresses
            .into_iter()
            .partition(|&a| a.as_numeric() < partition);
        let mut a_nodes = HashMap::new();
        let mut b_nodes = HashMap::new();
        for (address, node) in self.nodes.drain() {
            if address.as_numeric() < partition {
                a_nodes.insert(address, node);
            } else {
                b_nodes.insert(address, node);
            }
        }

        let a = NodeBucket {
            k: self.k,
            min: self.min.clone(),
            max: partition.clone(),
            addresses: a_addresses,
            nodes: a_nodes
        };
        let b = NodeBucket {
            k: self.k,
            min: partition.clone(),
            max: self.max.clone(),
            addresses: b_addresses,
            nodes: b_nodes
        };
        (a, b)
    }
}

#[cfg(test)]
mod tests {
    use address::{Address, Addressable};
    use super::NodeBucket;

    #[derive(Clone,Copy,Debug,PartialEq,Eq)]
    struct Node {
        pub address: Address
    }

    impl Node {
        fn new(address: Address) -> Node {
            Node { address: address }
        }
    }

    impl Addressable for Node {
        fn address(&self) -> Address {
            self.address
        }
    }

    #[test]
    fn test_insert() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        let node = Node::new(Address::for_content("some string"));
        bucket.insert(node);
        assert_eq!(bucket.addresses.len(), 1);
    }

    #[test]
    fn test_insert_duplicate() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        let a = Node::new(Address::for_content("node 1"));
        let b = Node::new(Address::for_content("node 2"));
        let c = Node::new(Address::for_content("node 1"));

        bucket.insert(a.clone());
        bucket.insert(b);
        bucket.insert(c);

        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes[&Address::for_content("node 1")], a);
    }

    #[test]
    fn test_insert_full() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(2);
        bucket.insert(Node::new(Address::for_content("node 1")));
        bucket.insert(Node::new(Address::for_content("node 2")));
        bucket.insert(Node::new(Address::for_content("node 3")));
        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes.get(&Address::for_content("node 3")), None);
    }

    #[test]
    fn test_is_full() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(2);
        assert!(!bucket.is_full());

        bucket.insert(Node::new(Address::for_content("node 1")));
        bucket.insert(Node::new(Address::for_content("node 2")));
        assert!(bucket.is_full());
    }

    #[test]
    fn test_contains() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        bucket.insert(Node::new(Address::for_content("node 1")));
        assert!(bucket.contains(&Address::for_content("node 1")));
    }

    #[test]
    fn test_covers() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        let address_1 = Address::from_str("0000000000000000000000000000000000000000");
        let address_2 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        assert!(bucket.covers(&address_1));
        assert!(bucket.covers(&address_2));
    }

    #[test]
    fn test_split() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(4);
        let node_1 = Node::new(Address::from_str("0000000000000000000000000000000000000000"));
        let node_2 = Node::new(Address::from_str("7fffffffffffffffffffffffffffffffffffffff"));
        let node_3 = Node::new(Address::from_str("8000000000000000000000000000000000000000"));
        let node_4 = Node::new(Address::from_str("ffffffffffffffffffffffffffffffffffffffff"));

        bucket.insert(node_1);
        bucket.insert(node_2);
        bucket.insert(node_3);
        bucket.insert(node_4);

        let (a, b) = bucket.split();

        // Splits up known address
        assert_eq!(a.addresses.len(), 2);
        assert_eq!(b.addresses.len(), 2);

        // Splits up known nodes
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")], node_1);
        assert_eq!(a.nodes[&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")], node_2);
        assert_eq!(b.nodes[&Address::from_str("8000000000000000000000000000000000000000")], node_3);
        assert_eq!(b.nodes[&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")], node_4);

        // Equitably covers address space
        assert!(a.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(!b.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(a.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!b.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!a.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(b.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(!a.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
        assert!(b.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
    }
}
<|endoftext|>


<commit_before>pub use self::chat::Chat;
pub use self::message_entity::MessageEntity;
pub use self::user::User;
pub use self::message::Message;
pub use self::update::Update;
pub use self::inline_keyboard::{Markup, Button};
pub use self::call_back_query::CallBackQuery;
pub use self::contact::Contact;

mod chat;
mod message_entity;
mod user;
mod message;
mod update;
mod inline_keyboard;
mod call_back_query;
mod contact;<commit_msg>changed names of imports from Markup and Button to InlineKeyboardMarkup and InlineKeyboardButton<commit_after>pub use self::chat::Chat;
pub use self::message_entity::MessageEntity;
pub use self::user::User;
pub use self::message::Message;
pub use self::update::Update;
pub use self::inline_keyboard::{InlineKeyboardMarkup, InlineKeyboardButton};
pub use self::call_back_query::CallBackQuery;
pub use self::contact::Contact;

mod chat;
mod message_entity;
mod user;
mod message;
mod update;
mod inline_keyboard;
mod call_back_query;
mod contact;<|endoftext|>


<commit_before>//! Support for patterns of arbitrary element types.
use std;

mod walk;
use self::walk::{action,Action,Walkable,Walker};

/// An iterator that produces its input item exactly once.
struct Once<'a,T: 'a>(Option<&'a T>);

impl<'a,T> Once<'a,T> {
    fn new(obj: &'a T) -> Once<'a,T> {
        Once(Some(obj))
    }
}

impl<'a,T> Iterator for Once<'a,T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        let out = self.0;
        self.0 = None;
        out
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        match self.0 {
            Some(..) => (1, Some(1)),
            None => (0, Some(0))
        }
    }
}

use self::PatternWalk::*;
enum PatternWalk {
    /// A pattern's first set is the set of elements that may begin a sequence
    /// matching that pattern.
    FirstSet,

    /// The atomic first set is like the first set above, but yields only the
    /// atomic values within the set.
    AtomicFirstSet
}

pub type ElementIterator<'a,T> = Box<Iterator<Item=&'a Element<T>> + 'a>;
pub type AtomicIterator<'a,T> = Box<Iterator<Item=&'a T> + 'a>;

/// Provides a method to determine whether a pattern is "nullable", i.e., can
/// match an empty sequence.
pub trait Nullable {
    /// Check if the token is nullable.
    fn is_nullable(&self) -> bool { false }
}

/// A component in a pattern.  Each element is either an atomic value, or
/// a Pattern trait object.
pub enum Element<T> {
    Atom(T),
    Pattern(Box<Pattern<T>>)
}

/// Interface for descriptions of syntactic patterns.
pub trait Pattern<T>: Walkable<PatternWalk::FirstSet,Element> + Walkable<PatternWalk::AtomicFirstSet,T> + Nullable {}

impl<'a,T> Nullable for Element<T> {
    fn is_nullable(&self) -> bool {
        match *self {
            Element::Atom(..) => false,
            Element::Pattern(ref pat) => pat.is_nullable(),
        }
    }
}

/// A sequence of atoms or subpatterns.
struct Sequence<T> {
    elements: Vec<Element<T>>
}

impl<'a,T: 'a> Walkable<AtomicFirstSet,&'a T> for Sequence<T> {
    type BaseIterator = std::slice::Iter<'a,Element<T>>;

    #[inline(always)]
    fn iter(&self) -> <Self as Walkable<AtomicFirstSet,&T>>::BaseIterator { self.elements.iter() }

    fn action<'b>(&self, element: &'b Element<T>) -> (Option<&T>, u8) {
        match *element {
            Element::Atom(..) =>
                Action{yield_value: Some(element),
                       recurse_on: None,
                       flags: action::TERMINATE},
            Element::Pattern(ref pat) =>
                Action{yield_value: None,
                       recurse_on: Some(element),
                       flags: if pat.is_nullable() { 0 } else { action::TERMINATE }}
        }
    }
}

impl<'a,T: 'a> Walkable<FirstSet,&'a Element<T>> for Sequence<T> {
    type BaseIterator = std::slice::Iter<'a,Element<T>>;

    #[inline(always)]
    fn iter(&self) -> <Self as Walkable<FirstSet,&Element<T>>>::BaseIterator { self.elements.iter() }

    #[inline(always)]
    fn action<'b>(&self, element: &'b Element<T>) -> (Option<&Element<T>>, u8) {
        match *element {
            Element::Atom(..) =>
                Action{yield_value: Some(element),
                       recurse_on: None,
                       flags: action::TERMINATE},
            Element::Pattern(ref pat) =>
                Action{yield_value: Some(element),
                       recurse_on: Some(element),
                       flags: if pat.is_nullable() { 0 } else { action::TERMINATE }}
        }
    }
}

impl<T> Nullable for Sequence<T> {
    fn is_nullable(&self) -> bool {
        if self.elements.is_empty() { true }
        else {
            for elt in self.elements.iter() {
                match *elt {
                    Element::Atom(..) => return false,
                    Element::Pattern(pat) => if ! pat.is_nullable() { return false; }
                }
            }
            true
        }
    }
}
<commit_msg>pattern: use traits-tags for walk trait discriminators<commit_after>//! Support for patterns of arbitrary element types.
use std;

mod walk;
use self::walk::{action,Action,Walkable,Walker};

/// An iterator that produces its input item exactly once.
struct Once<'a,T: 'a>(Option<&'a T>);

impl<'a,T> Once<'a,T> {
    fn new(obj: &'a T) -> Once<'a,T> {
        Once(Some(obj))
    }
}

impl<'a,T> Iterator for Once<'a,T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        let out = self.0;
        self.0 = None;
        out
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        match self.0 {
            Some(..) => (1, Some(1)),
            None => (0, Some(0))
        }
    }
}

/// A pattern's first set is the set of elements that may begin a sequence
/// matching that pattern.
trait FirstSet: MarkerTrait {}
/// The atomic first set is like the first set above, but yields only the
/// atomic values within the set.
trait AtomicFirstSet: MarkerTrait {}
pub type ElementIterator<'a,T> = Box<Iterator<Item=&'a Element<T>> + 'a>;
pub type AtomicIterator<'a,T> = Box<Iterator<Item=&'a T> + 'a>;

/// Provides a method to determine whether a pattern is "nullable", i.e., can
/// match an empty sequence.
pub trait Nullable {
    /// Check if the token is nullable.
    fn is_nullable(&self) -> bool { false }
}

/// A component in a pattern.  Each element is either an atomic value, or
/// a Pattern trait object.
pub enum Element<T> {
    Atom(T),
    Pattern(Box<Pattern<T>>)
}

/// Interface for descriptions of syntactic patterns.
pub trait Pattern<T>: Walkable<PatternWalk::FirstSet,Element> + Walkable<PatternWalk::AtomicFirstSet,T> + Nullable {}

impl<'a,T> Nullable for Element<T> {
    fn is_nullable(&self) -> bool {
        match *self {
            Element::Atom(..) => false,
            Element::Pattern(ref pat) => pat.is_nullable(),
        }
    }
}

/// A sequence of atoms or subpatterns.
struct Sequence<T> {
    elements: Vec<Element<T>>
}

impl<'a,T: 'a> Walkable<AtomicFirstSet,&'a T> for Sequence<T> {
    type BaseIterator = std::slice::Iter<'a,Element<T>>;

    #[inline(always)]
    fn iter(&self) -> <Self as Walkable<AtomicFirstSet,&T>>::BaseIterator { self.elements.iter() }

    fn action<'b>(&self, element: &'b Element<T>) -> (Option<&T>, u8) {
        match *element {
            Element::Atom(..) =>
                Action{yield_value: Some(element),
                       recurse_on: None,
                       flags: action::TERMINATE},
            Element::Pattern(ref pat) =>
                Action{yield_value: None,
                       recurse_on: Some(element),
                       flags: if pat.is_nullable() { 0 } else { action::TERMINATE }}
        }
    }
}

impl<'a,T: 'a> Walkable<FirstSet,&'a Element<T>> for Sequence<T> {
    type BaseIterator = std::slice::Iter<'a,Element<T>>;

    #[inline(always)]
    fn iter(&self) -> <Self as Walkable<FirstSet,&Element<T>>>::BaseIterator { self.elements.iter() }

    #[inline(always)]
    fn action<'b>(&self, element: &'b Element<T>) -> (Option<&Element<T>>, u8) {
        match *element {
            Element::Atom(..) =>
                Action{yield_value: Some(element),
                       recurse_on: None,
                       flags: action::TERMINATE},
            Element::Pattern(ref pat) =>
                Action{yield_value: Some(element),
                       recurse_on: Some(element),
                       flags: if pat.is_nullable() { 0 } else { action::TERMINATE }}
        }
    }
}

impl<T> Nullable for Sequence<T> {
    fn is_nullable(&self) -> bool {
        if self.elements.is_empty() { true }
        else {
            for elt in self.elements.iter() {
                match *elt {
                    Element::Atom(..) => return false,
                    Element::Pattern(pat) => if ! pat.is_nullable() { return false; }
                }
            }
            true
        }
    }
}
<|endoftext|>


<commit_before>mod test;

use std::rc::Rc;
use std::cell::RefCell;

use core::*;
use lexer::*;
use parser::*;
use walker::*;

pub struct Printer {
    vm: Rc<RefCell<Heliqs>>,
}

impl Printer {
    pub fn new(vm: Rc<RefCell<Heliqs>>) -> Self {
        Printer{ vm: vm }
    }

    pub fn print(&self) -> String {
        if let Some(entrypoint) = self.vm.borrow().entry() {
            self.print_aexp(entrypoint, 0)
        } else {
            "".to_string()
        }
    }

    pub fn print_aexp(&self, i: NodeId, nest_level: u32) -> String {
        let vm = self.vm.borrow();
        let &Node(_, ref epiq) = vm.get_epiq(i);
        match **epiq {
            Epiq::Unit => ";".to_string(),
            Epiq::Tval => "^T".to_string(),
            Epiq::Fval => "^F".to_string(),
            Epiq::Name(ref n) => n.to_string(),
            Epiq::Uit8(ref n) => format!("{}", n),
            Epiq::Text(ref n) => format!("\"{}\"", n),
            Epiq::Prim(ref n) => format!("Prim({})", n),
            Epiq::Tpiq { ref o, p, q } => self.print_piq(o, p, q, nest_level),
            Epiq::Mpiq { ref o, p, q } => self.print_piq(&format!("^{}", o), p, q, nest_level),
            Epiq::Eval(p, q) => self.print_piq(">", p, q, nest_level),
            Epiq::Quot(p, q) => self.print_piq("|", p, q, nest_level),
            Epiq::Lpiq(p, q) => self.print_piq(":", p, q, nest_level),
            Epiq::Appl(p, q) => self.print_piq("!", p, q, nest_level),
            Epiq::Rslv(p, q) => self.print_piq("@", p, q, nest_level),
            Epiq::Cond(p, q) => self.print_piq("?", p, q, nest_level),
            Epiq::Envn(p, q) => self.print_piq("%", p, q, nest_level),
            Epiq::Bind(p, q) => self.print_piq("#", p, q, nest_level),
            Epiq::Accs(p, q) => self.print_piq(".", p, q, nest_level),
            Epiq::Lmbd(p, q) => self.print_piq(r"\", p, q, nest_level),

            // _ => "".to_string(),
        }
    }

    fn print_piq(&self, otag: &str, p: NodeId, q:NodeId, nest_level: u32) -> String {
        format!("{}({} {})", otag, self.print_aexp(p, nest_level + 1), self.print_aexp(q, nest_level + 1))
    }
}

pub fn print_str(left: &str, right: &str) {
    let mut iter = left.bytes();
    let scanners: &Vec<&Scanner> = &all_scanners!();
    let lexer = Lexer::new(&mut iter, scanners);

    let vm = Rc::new(RefCell::new(Heliqs::new()));
    let vm2 = vm.clone();
    let mut parser = Parser::new(lexer, vm);
    let _parsed_ast = parser.parse();

    let printer = Printer::new(vm2);

    assert_eq!(printer.print(), right);
}

pub fn evaled_str(left: &str) -> String {
    let mut iter = left.bytes();
    let scanners: &Vec<&Scanner> = &all_scanners!();
    let lexer = Lexer::new(&mut iter, scanners);

    let vm = Rc::new(RefCell::new(Heliqs::new()));
    let vm2 = vm.clone();
    let vm3 = vm.clone();
    let mut parser = Parser::new(lexer, vm);
    parser.parse();

    let walker = Walker::new(vm2);
    walker.walk();

    let printer = Printer::new(vm3);
    printer.print().to_string()
}

pub fn print_evaled_str(left: &str, right: &str) {
    let result = evaled_str(left);
    assert_eq!(result, right);
}

/// leftを評価したらちゃんとrightになるかどうかのテスト
pub fn print_syntax_sugar(left: &str, right: &str) {
    let result_left = evaled_str(left);
    let result_right = evaled_str(right);
    assert_eq!(result_left, result_right);
}

pub fn only_evaluate(s: &str) {
    let mut iter = s.bytes();
    let scanners: &Vec<&Scanner> = &all_scanners!();
    let lexer = Lexer::new(&mut iter, scanners);

    let vm = Rc::new(RefCell::new(Heliqs::new()));
    let vm2 = vm.clone();

    let mut parser = Parser::new(lexer, vm);
    parser.parse();

    let walker = Walker::new(vm2);
    walker.walk();
}

fn craete_vm<'a>() -> Rc<RefCell<Heliqs>> {
    Rc::new(RefCell::new(Heliqs::new()))
}
<commit_msg>fix dead code<commit_after>mod test;

use std::rc::Rc;
use std::cell::RefCell;

use core::*;
use lexer::*;
use parser::*;
use walker::*;

pub struct Printer {
    vm: Rc<RefCell<Heliqs>>,
}

impl Printer {
    pub fn new(vm: Rc<RefCell<Heliqs>>) -> Self {
        Printer{ vm: vm }
    }

    pub fn print(&self) -> String {
        if let Some(entrypoint) = self.vm.borrow().entry() {
            self.print_aexp(entrypoint, 0)
        } else {
            "".to_string()
        }
    }

    pub fn print_aexp(&self, i: NodeId, nest_level: u32) -> String {
        let vm = self.vm.borrow();
        let &Node(_, ref epiq) = vm.get_epiq(i);
        match **epiq {
            Epiq::Unit => ";".to_string(),
            Epiq::Tval => "^T".to_string(),
            Epiq::Fval => "^F".to_string(),
            Epiq::Name(ref n) => n.to_string(),
            Epiq::Uit8(ref n) => format!("{}", n),
            Epiq::Text(ref n) => format!("\"{}\"", n),
            Epiq::Prim(ref n) => format!("Prim({})", n),
            Epiq::Tpiq { ref o, p, q } => self.print_piq(o, p, q, nest_level),
            Epiq::Mpiq { ref o, p, q } => self.print_piq(&format!("^{}", o), p, q, nest_level),
            Epiq::Eval(p, q) => self.print_piq(">", p, q, nest_level),
            Epiq::Quot(p, q) => self.print_piq("|", p, q, nest_level),
            Epiq::Lpiq(p, q) => self.print_piq(":", p, q, nest_level),
            Epiq::Appl(p, q) => self.print_piq("!", p, q, nest_level),
            Epiq::Rslv(p, q) => self.print_piq("@", p, q, nest_level),
            Epiq::Cond(p, q) => self.print_piq("?", p, q, nest_level),
            Epiq::Envn(p, q) => self.print_piq("%", p, q, nest_level),
            Epiq::Bind(p, q) => self.print_piq("#", p, q, nest_level),
            Epiq::Accs(p, q) => self.print_piq(".", p, q, nest_level),
            Epiq::Lmbd(p, q) => self.print_piq(r"\", p, q, nest_level),

            // _ => "".to_string(),
        }
    }

    fn print_piq(&self, otag: &str, p: NodeId, q:NodeId, nest_level: u32) -> String {
        format!("{}({} {})", otag, self.print_aexp(p, nest_level + 1), self.print_aexp(q, nest_level + 1))
    }
}

pub fn print_str(left: &str, right: &str) {
    let mut iter = left.bytes();
    let scanners: &Vec<&Scanner> = &all_scanners!();
    let lexer = Lexer::new(&mut iter, scanners);

    let vm = Rc::new(RefCell::new(Heliqs::new()));
    let vm2 = vm.clone();
    let mut parser = Parser::new(lexer, vm);
    let _parsed_ast = parser.parse();

    let printer = Printer::new(vm2);

    assert_eq!(printer.print(), right);
}

pub fn evaled_str(left: &str) -> String {
    let mut iter = left.bytes();
    let scanners: &Vec<&Scanner> = &all_scanners!();
    let lexer = Lexer::new(&mut iter, scanners);

    let vm = Rc::new(RefCell::new(Heliqs::new()));
    let vm2 = vm.clone();
    let vm3 = vm.clone();
    let mut parser = Parser::new(lexer, vm);
    parser.parse();

    let walker = Walker::new(vm2);
    walker.walk();

    let printer = Printer::new(vm3);
    printer.print()
}

pub fn print_evaled_str(left: &str, right: &str) {
    let result = evaled_str(left);
    assert_eq!(result, right);
}

/// leftを評価したらちゃんとrightになるかどうかのテスト
pub fn print_syntax_sugar(left: &str, right: &str) {
    let result_left = evaled_str(left);
    let result_right = evaled_str(right);
    assert_eq!(result_left, result_right);
}

pub fn only_evaluate(s: &str) {
    let mut iter = s.bytes();
    let scanners: &Vec<&Scanner> = &all_scanners!();
    let lexer = Lexer::new(&mut iter, scanners);

    let vm = Rc::new(RefCell::new(Heliqs::new()));
    let vm2 = vm.clone();

    let mut parser = Parser::new(lexer, vm);
    parser.parse();

    let walker = Walker::new(vm2);
    walker.walk();
}
<|endoftext|>


<commit_before>use core::{mem, ptr};
use raw::bitmask::BitMask;
use raw::EMPTY;

// Use the native word size as the group size. Using a 64-bit group size on
// a 32-bit architecture will just end up being more expensive because
// shifts and multiplies will need to be emulated.
#[cfg(any(
    target_pointer_width = "64",
    target_arch = "aarch64",
    target_arch = "x86_64",
))]
type GroupWord = u64;
#[cfg(all(
    target_pointer_width = "32",
    not(target_arch = "aarch64"),
    not(target_arch = "x86_64"),
))]
type GroupWord = u32;

pub type BitMaskWord = GroupWord;
pub const BITMASK_SHIFT: u32 = 3;
pub const BITMASK_MASK: GroupWord = 0x8080808080808080u64 as GroupWord;

/// Helper function to replicate a byte across a `GroupWord`.
#[inline]
fn repeat(byte: u8) -> GroupWord {
    let repeat = byte as GroupWord;
    let repeat = repeat | repeat.wrapping_shl(8);
    let repeat = repeat | repeat.wrapping_shl(16);
    // This last line is a no-op with a 32-bit GroupWord
    repeat | repeat.wrapping_shl(32)
}

/// Abstraction over a group of control bytes which can be scanned in
/// parallel.
///
/// This implementation uses a word-sized integer.
pub struct Group(GroupWord);

// We perform all operations in the native endianess, and convert to
// little-endian just before creating a BitMask. The can potentially
// enable the compiler to eliminate unnecessary byte swaps if we are
// only checking whether a BitMask is empty.
impl Group {
    /// Number of bytes in the group.
    pub const WIDTH: usize = mem::size_of::<Self>();

    /// Returns a full group of empty bytes, suitable for use as the initial
    /// value for an empty hash table.
    ///
    /// This is guaranteed to be aligned to the group size.
    #[inline]
    pub fn static_empty() -> &'static [u8] {
        #[repr(C)]
        struct Dummy {
            _align: [GroupWord; 0],
            bytes: [u8; Group::WIDTH],
        };
        const DUMMY: Dummy = Dummy {
            _align: [],
            bytes: [EMPTY; Group::WIDTH],
        };
        &DUMMY.bytes
    }

    /// Loads a group of bytes starting at the given address.
    #[inline]
    pub unsafe fn load(ptr: *const u8) -> Group {
        Group(ptr::read_unaligned(ptr as *const _))
    }

    /// Loads a group of bytes starting at the given address, which must be
    /// aligned to `WIDTH`.
    #[inline]
    pub unsafe fn load_aligned(ptr: *const u8) -> Group {
        Group(ptr::read(ptr as *const _))
    }

    /// Stores the group of bytes to the given address, which must be
    /// aligned to `WIDTH`.
    #[inline]
    pub unsafe fn store_aligned(&self, ptr: *mut u8) {
        ptr::write(ptr as *mut _, self.0);
    }

    /// Returns a `BitMask` indicating all bytes in the group which *may*
    /// have the given value.
    ///
    /// This function may return a false positive in certain cases where
    /// the byte in the group differs from the searched value only in its
    /// lowest bit. This is fine because:
    /// - This never happens for `EMPTY` and `DELETED`, only full entries.
    /// - The check for key equality will catch these.
    /// - This only happens if there is at least 1 true match.
    /// - The chance of this happening is very low (< 1% chance per byte).
    #[inline]
    pub fn match_byte(&self, byte: u8) -> BitMask {
        // This algorithm is derived from
        // http://graphics.stanford.edu/~seander/bithacks.html##ValueInWord
        let cmp = self.0 ^ repeat(byte);
        BitMask(((cmp - repeat(0x01)) & !cmp & repeat(0x80)).to_le())
    }

    /// Returns a `BitMask` indicating all bytes in the group which are
    /// `EMPTY`.
    #[inline]
    pub fn match_empty(&self) -> BitMask {
        BitMask((self.0 & (self.0 << 1) & repeat(0x80)).to_le())
    }

    /// Returns a `BitMask` indicating all bytes in the group which are
    /// `EMPTY` pr `DELETED`.
    #[inline]
    pub fn match_empty_or_deleted(&self) -> BitMask {
        BitMask((self.0 & repeat(0x80)).to_le())
    }

    /// Performs the following transformation on all bytes in the group:
    /// - `EMPTY => EMPTY`
    /// - `DELETED => EMPTY`
    /// - `FULL => DELETED`
    #[inline]
    pub fn convert_special_to_empty_and_full_to_deleted(&self) -> Group {
        Group(((self.0 & repeat(0x80)) >> 7) * 0xff)
    }
}
<commit_msg>Fix subtraction overflow in generic::Group::match_byte<commit_after>use core::{mem, ptr};
use raw::bitmask::BitMask;
use raw::EMPTY;

// Use the native word size as the group size. Using a 64-bit group size on
// a 32-bit architecture will just end up being more expensive because
// shifts and multiplies will need to be emulated.
#[cfg(any(
    target_pointer_width = "64",
    target_arch = "aarch64",
    target_arch = "x86_64",
))]
type GroupWord = u64;
#[cfg(all(
    target_pointer_width = "32",
    not(target_arch = "aarch64"),
    not(target_arch = "x86_64"),
))]
type GroupWord = u32;

pub type BitMaskWord = GroupWord;
pub const BITMASK_SHIFT: u32 = 3;
pub const BITMASK_MASK: GroupWord = 0x8080808080808080u64 as GroupWord;

/// Helper function to replicate a byte across a `GroupWord`.
#[inline]
fn repeat(byte: u8) -> GroupWord {
    let repeat = byte as GroupWord;
    let repeat = repeat | repeat.wrapping_shl(8);
    let repeat = repeat | repeat.wrapping_shl(16);
    // This last line is a no-op with a 32-bit GroupWord
    repeat | repeat.wrapping_shl(32)
}

/// Abstraction over a group of control bytes which can be scanned in
/// parallel.
///
/// This implementation uses a word-sized integer.
pub struct Group(GroupWord);

// We perform all operations in the native endianess, and convert to
// little-endian just before creating a BitMask. The can potentially
// enable the compiler to eliminate unnecessary byte swaps if we are
// only checking whether a BitMask is empty.
impl Group {
    /// Number of bytes in the group.
    pub const WIDTH: usize = mem::size_of::<Self>();

    /// Returns a full group of empty bytes, suitable for use as the initial
    /// value for an empty hash table.
    ///
    /// This is guaranteed to be aligned to the group size.
    #[inline]
    pub fn static_empty() -> &'static [u8] {
        #[repr(C)]
        struct Dummy {
            _align: [GroupWord; 0],
            bytes: [u8; Group::WIDTH],
        };
        const DUMMY: Dummy = Dummy {
            _align: [],
            bytes: [EMPTY; Group::WIDTH],
        };
        &DUMMY.bytes
    }

    /// Loads a group of bytes starting at the given address.
    #[inline]
    pub unsafe fn load(ptr: *const u8) -> Group {
        Group(ptr::read_unaligned(ptr as *const _))
    }

    /// Loads a group of bytes starting at the given address, which must be
    /// aligned to `WIDTH`.
    #[inline]
    pub unsafe fn load_aligned(ptr: *const u8) -> Group {
        Group(ptr::read(ptr as *const _))
    }

    /// Stores the group of bytes to the given address, which must be
    /// aligned to `WIDTH`.
    #[inline]
    pub unsafe fn store_aligned(&self, ptr: *mut u8) {
        ptr::write(ptr as *mut _, self.0);
    }

    /// Returns a `BitMask` indicating all bytes in the group which *may*
    /// have the given value.
    ///
    /// This function may return a false positive in certain cases where
    /// the byte in the group differs from the searched value only in its
    /// lowest bit. This is fine because:
    /// - This never happens for `EMPTY` and `DELETED`, only full entries.
    /// - The check for key equality will catch these.
    /// - This only happens if there is at least 1 true match.
    /// - The chance of this happening is very low (< 1% chance per byte).
    #[inline]
    pub fn match_byte(&self, byte: u8) -> BitMask {
        // This algorithm is derived from
        // http://graphics.stanford.edu/~seander/bithacks.html##ValueInWord
        let cmp = self.0 ^ repeat(byte);
        BitMask((cmp.wrapping_sub(repeat(0x01)) & !cmp & repeat(0x80)).to_le())
    }

    /// Returns a `BitMask` indicating all bytes in the group which are
    /// `EMPTY`.
    #[inline]
    pub fn match_empty(&self) -> BitMask {
        BitMask((self.0 & (self.0 << 1) & repeat(0x80)).to_le())
    }

    /// Returns a `BitMask` indicating all bytes in the group which are
    /// `EMPTY` pr `DELETED`.
    #[inline]
    pub fn match_empty_or_deleted(&self) -> BitMask {
        BitMask((self.0 & repeat(0x80)).to_le())
    }

    /// Performs the following transformation on all bytes in the group:
    /// - `EMPTY => EMPTY`
    /// - `DELETED => EMPTY`
    /// - `FULL => DELETED`
    #[inline]
    pub fn convert_special_to_empty_and_full_to_deleted(&self) -> Group {
        Group(((self.0 & repeat(0x80)) >> 7) * 0xff)
    }
}
<|endoftext|>


<commit_before>//
// Copyright (c) Pirmin Kalberer. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

use datasource::{Datasource,DatasourceInput};
use datasource::PostgisInput;
use core::grid::Grid;
use core::layer::Layer;
use core::Config;
use mvt::tile::Tile;
use mvt::vector_tile;
use cache::{Cache,Tilecache,Nocache};
use toml;
use rustc_serialize::json::{Json, ToJson};

/// Collection of layers in one MVT
pub struct Tileset {
    pub name: String,
    pub layers: Vec<Layer>,
}

/// Mapbox Vector Tile Service
pub struct MvtService {
    pub input: PostgisInput,
    pub grid: Grid,
    pub tilesets: Vec<Tileset>,
    pub cache: Tilecache,
}

impl MvtService {
    fn get_tileset(&self, name: &str) -> Vec<&Layer> {
        let tileset = self.tilesets.iter().find(|t| t.name == name);
        match tileset {
            Some(set) => set.layers.iter().map(|l| l).collect(),
            None => Vec::new()
        }
    }
    fn get_tilejson_infos(&self, tileset: &str) -> (Json, Json, Json) {
        let layers = self.get_tileset(tileset);
        let metadata = Json::from_str(r#"
        {
            "id": "t_rex",
            "name": "t_rex",
            "description": "T-Rex cache",
            "attribution": "",
            "type": "baselayer",
            "format": "pbf",
            "version": "2.0",
            "scheme": "tms",
            "bounds": "-180.0,-90.0,180.0,90.0",
            "minzoom": "0",
            "maxzoom": "14",
            "center": "0.0,0.0,2",
            "mtime": "1463000297761",
            "basename": "t_rex.mbtiles",
            "filesize": "0"
        }"#).unwrap();
        let layers_metadata: Vec<(String,String)> = layers.iter().map(|layer| {
            let meta = layer.metadata();
            let fields = self.input.detect_columns(&layer, 0);
            let fields_json: Vec<String> = fields.iter().map(|f| format!("\"{}\": \"\"", f)).collect();
            let layers = format!(r#"{{
                "id": "{}",
                "name": "{}",
                "description": "{}",
                "srs": "{}",
                "properties": {{
                    "minzoom": {},
                    "maxzoom": {},
                    "buffer-size": {}
                }},
                "fields": {{
                    {}
                }}
                }}"#, meta.get("id").unwrap(), meta.get("name").unwrap(),  meta.get("description").unwrap(),
                meta.get("srs").unwrap(), meta.get("minzoom").unwrap(), meta.get("maxzoom").unwrap(),
                meta.get("buffer-size").unwrap(), fields_json.join(","));
            let vector_layers = format!(r#"{{
                "id": "{}",
                "description": "{}",
                "minzoom": {},
                "maxzoom": {},
                "fields": {{
                    {}
                }}
                }}"#, meta.get("id").unwrap(), meta.get("description").unwrap(),
                meta.get("minzoom").unwrap(), meta.get("maxzoom").unwrap(), fields_json.join(","));
            (layers, vector_layers)
        }).collect();
        let layers: Vec<String> = layers_metadata.iter().map(|&(ref l, _)| l.clone()).collect();
        let layers_json = Json::from_str(&format!("[{}]", layers.join(","))).unwrap();
        let vector_layers: Vec<String> = layers_metadata.iter().map(|&(_, ref l)| l.clone()).collect();
        let vector_layers_json = Json::from_str(&format!("[{}]", vector_layers.join(","))).unwrap();
        (metadata, layers_json, vector_layers_json)
    }
    pub fn get_tilejson(&self, tileset: &str) -> String {
        let (mut metadata, _layers, vector_layers) = self.get_tilejson_infos(tileset);
        let mut obj = metadata.as_object_mut().unwrap();
        let url = Json::from_str(&format!("[\"http://127.0.0.1:6767/{}/{{z}}/{{x}}/{{y}}.pbf\"]", tileset)).unwrap();
        obj.insert("tiles".to_string(), url);
        obj.insert("vector_layers".to_string(), vector_layers);
        obj.to_json().to_string()
    }
    pub fn get_metadata(&self, tileset: &str) -> String {
        let (mut metadata, layers, vector_layers) = self.get_tilejson_infos(tileset);
        let json_str = format!(r#"
        {{
          "Layer": {},
          "vector_layers": {}
        }}"#, layers.to_string(), vector_layers.to_string());
        let metadata_vector_layers = Json::from_str(&json_str).unwrap();
        let mut obj = metadata.as_object_mut().unwrap();
        obj.insert("json".to_string(), metadata_vector_layers.to_string().to_json());
        obj.to_json().to_string()
    }
    /// Create vector tile from input at x, y, z
    pub fn tile(&self, tileset: &str, xtile: u16, ytile: u16, zoom: u16) -> vector_tile::Tile {
        let extent = self.grid.tile_extent_reverse_y(xtile, ytile, zoom);
        debug!("MVT tile request {:?}", extent);
        let mut tile = Tile::new(&extent, 4096, true);
        for layer in self.get_tileset(tileset) {
            let mut mvt_layer = tile.new_layer(layer);
            self.input.retrieve_features(&layer, &extent, zoom, |feat| {
                tile.add_feature(&mut mvt_layer, feat);
            });
            tile.add_layer(mvt_layer);
        }
        tile.mvt_tile
    }
    /// Fetch or create vector tile from input at x, y, z
    pub fn tile_cached(&self, tileset: &str, xtile: u16, ytile: u16, zoom: u16, gzip: bool) -> Vec<u8> {
        let path = format!("{}/{}/{}/{}.pbf", tileset, zoom, xtile, ytile);

        let mut tile: Option<Vec<u8>> = None;
        self.cache.read(&path, |mut f| {
            let mut data = Vec::new();
            let _ = f.read_to_end(&mut data);
            tile = Some(data);
        });
        if tile.is_some() {
            //TODO: unzip if gzip == false
            return tile.unwrap()
        }

        let mvt_tile = self.tile(tileset, xtile, ytile, zoom);

        let mut tilegz = Vec::new();
        Tile::write_gz_to(&mut tilegz, &mvt_tile);
        let _ = self.cache.write(&path, &tilegz);

        //TODO: return unzipped if gzip == false
        tilegz
    }
}

impl Tileset {
    pub fn tilesets_from_config(config: &toml::Value) -> Result<Vec<Self>, String> {
        config.lookup("tileset")
              .ok_or("Missing configuration entry [[tileset]]".to_string())
              .and_then(|tarr| tarr.as_slice().ok_or("Array type for [[tileset]] entry expected".to_string()))
              .and_then(|tilesets| {
                  Ok(tilesets.iter().map(|tileset| Tileset::from_config(tileset).unwrap()).collect())
              })
    }
}

impl Config<Tileset> for Tileset {
    fn from_config(config: &toml::Value) -> Result<Self, String> {
        let name = config.lookup("name")
                         .ok_or("Missing configuration entry name in [[tileset]]".to_string())
                         .and_then(|val| val.as_str().ok_or("tileset.name entry is not a string".to_string()))
                         .map(|v| v.to_string());
        let layers = try!(Layer::layers_from_config(config));
        name.and_then(|n|
            Ok(Tileset{name: n, layers: layers})
        )
    }
    fn gen_config() -> String {
        let mut config = String::new();
        config.push_str(&Layer::gen_config());
        config
    }
    fn gen_runtime_config(&self) -> String {
        let mut config = String::new();
        for layer in &self.layers {
            config.push_str(&layer.gen_runtime_config());
        }
        config
    }
}

impl Config<MvtService> for MvtService {
    fn from_config(config: &toml::Value) -> Result<Self, String> {
        let pg = try!(PostgisInput::from_config(config));
        let grid = try!(Grid::from_config(config));
        let tilesets = try!(Tileset::tilesets_from_config(config));
        let cache = try!(Tilecache::from_config(config));
        Ok(MvtService {input: pg, grid: grid,
                       tilesets: tilesets, cache: cache})
    }
    fn gen_config() -> String {
        let mut config = String::new();
        config.push_str(TOML_SERVICES);
        config.push_str(&Datasource::gen_config());
        config.push_str(&Grid::gen_config());
        config.push_str(&Tileset::gen_config());
        config.push_str(&Tilecache::gen_config());
        config
    }
    fn gen_runtime_config(&self) -> String {
        let mut config = String::new();
        config.push_str(TOML_SERVICES);
        config.push_str(&self.input.gen_runtime_config());
        config.push_str(&self.grid.gen_runtime_config());
        for tileset in &self.tilesets {
            config.push_str(&tileset.gen_runtime_config());
        }
        config.push_str(&self.cache.gen_runtime_config());
        config
    }
}

const TOML_SERVICES: &'static str = r#"# t-rex configuration

[services]
mvt = true
"#;

#[test]
pub fn test_tile_query() {
    use std::io::{self,Write};
    use std::env;

    let pg: PostgisInput = match env::var("DBCONN") {
        Result::Ok(val) => Some(PostgisInput {connection_url: val}),
        Result::Err(_) => { write!(&mut io::stdout(), "skipped ").unwrap(); return; }
    }.unwrap();
    let grid = Grid::web_mercator();
    let mut layer = Layer::new("points");
    layer.table_name = Some(String::from("ne_10m_populated_places"));
    layer.geometry_field = Some(String::from("wkb_geometry"));
    layer.geometry_type = Some(String::from("POINT"));
    layer.query_limit = Some(1);
    let tileset = Tileset{name: "points".to_string(), layers: vec![layer]};
    let service = MvtService {input: pg, grid: grid,
                              tilesets: vec![tileset], cache: Tilecache::Nocache(Nocache)};

    let mvt_tile = service.tile("points", 33, 22, 6);
    println!("{:#?}", mvt_tile);
    let expected = r#"Tile {
    layers: [
        Tile_Layer {
            version: Some(
                2
            ),
            name: Some("points"),
            features: [
                Tile_Feature {
                    id: None,
                    tags: [],
                    field_type: Some(
                        POINT
                    ),
                    geometry: [
                        9,
                        2504,
                        3390
                    ],
                    unknown_fields: UnknownFields {
                        fields: None
                    },
                    cached_size: Cell {
                        value: 0
                    }
                }
            ],
            keys: [],
            values: [],
            extent: Some(
                4096
            ),
            unknown_fields: UnknownFields {
                fields: None
            },
            cached_size: Cell {
                value: 0
            }
        }
    ],
    unknown_fields: UnknownFields {
        fields: None
    },
    cached_size: Cell {
        value: 0
    }
}"#;
    assert_eq!(expected, &*format!("{:#?}", mvt_tile));
}

#[test]
pub fn test_metadata() {
    use core::read_config;
    use std::io::{self,Write};
    use std::env;

    if env::var("DBCONN").is_err() {
        write!(&mut io::stdout(), "skipped ").unwrap();
        return;
    }

    let config = read_config("src/test/example.cfg").unwrap();
    let service = MvtService::from_config(&config).unwrap();
    let metadata = service.get_metadata("points");
    println!("{}", metadata);
    let format = r#""format":"pbf""#;
    assert!(metadata.contains(format));
    let jsonmeta = r#"\"vector_layers\":"#;
    assert!(metadata.contains(jsonmeta));
}

#[test]
pub fn test_gen_config() {
    let expected = r#"# t-rex configuration

[services]
mvt = true

[datasource]
type = "postgis"
# Connection specification (https://github.com/sfackler/rust-postgres#connecting)
url = "postgresql://user:pass@host:port/database"

[grid]
# Predefined grids: web_mercator, wgs84
predefined = "web_mercator"

[[tileset]]
name = "points"

[[tileset.layer]]
name = "points"
table_name = "mytable"
geometry_field = "wkb_geometry"
geometry_type = "POINT"
#fid_field = "id"
#query = "SELECT name,wkb_geometry FROM mytable"

#[cache.file]
#base = "/tmp/mvtcache"
"#;
    println!("{}", &MvtService::gen_config());
    assert_eq!(expected, &MvtService::gen_config());
}
<commit_msg>Minor tiljson cleanups<commit_after>//
// Copyright (c) Pirmin Kalberer. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

use datasource::{Datasource,DatasourceInput};
use datasource::PostgisInput;
use core::grid::Grid;
use core::layer::Layer;
use core::Config;
use mvt::tile::Tile;
use mvt::vector_tile;
use cache::{Cache,Tilecache,Nocache};
use toml;
use rustc_serialize::json::{Json, ToJson};

/// Collection of layers in one MVT
pub struct Tileset {
    pub name: String,
    pub layers: Vec<Layer>,
}

/// Mapbox Vector Tile Service
pub struct MvtService {
    pub input: PostgisInput,
    pub grid: Grid,
    pub tilesets: Vec<Tileset>,
    pub cache: Tilecache,
}

impl MvtService {
    fn get_tileset(&self, name: &str) -> Vec<&Layer> {
        let tileset = self.tilesets.iter().find(|t| t.name == name);
        match tileset {
            Some(set) => set.layers.iter().map(|l| l).collect(),
            None => Vec::new()
        }
    }
    fn get_tilejson_infos(&self, tileset: &str) -> (Json, Json, Json) {
        let layers = self.get_tileset(tileset);
        let metadata = Json::from_str(&format!(r#"
        {{
            "id": "{}",
            "name": "{}",
            "description": "{}",
            "attribution": "",
            "format": "pbf",
            "version": "2.0.0",
            "scheme": "xyz",
            "bounds": [-180.0,-90.0,180.0,90.0],
            "minzoom": 0,
            "maxzoom": 14,
            "center": "0.0,0.0,2",
            "basename": "{}"
        }}"#, tileset, tileset, tileset, tileset)).unwrap();
        let layers_metadata: Vec<(String,String)> = layers.iter().map(|layer| {
            let meta = layer.metadata();
            let fields = self.input.detect_columns(&layer, 0);
            let fields_json: Vec<String> = fields.iter().map(|f| format!("\"{}\": \"\"", f)).collect();
            let layers = format!(r#"{{
                "id": "{}",
                "name": "{}",
                "description": "{}",
                "srs": "{}",
                "properties": {{
                    "minzoom": {},
                    "maxzoom": {},
                    "buffer-size": {}
                }},
                "fields": {{
                    {}
                }}
                }}"#, meta.get("id").unwrap(), meta.get("name").unwrap(),  meta.get("description").unwrap(),
                meta.get("srs").unwrap(), meta.get("minzoom").unwrap(), meta.get("maxzoom").unwrap(),
                meta.get("buffer-size").unwrap(), fields_json.join(","));
            let vector_layers = format!(r#"{{
                "id": "{}",
                "description": "{}",
                "minzoom": {},
                "maxzoom": {},
                "fields": {{
                    {}
                }}
                }}"#, meta.get("id").unwrap(), meta.get("description").unwrap(),
                meta.get("minzoom").unwrap(), meta.get("maxzoom").unwrap(), fields_json.join(","));
            (layers, vector_layers)
        }).collect();
        let layers: Vec<String> = layers_metadata.iter().map(|&(ref l, _)| l.clone()).collect();
        let layers_json = Json::from_str(&format!("[{}]", layers.join(","))).unwrap();
        let vector_layers: Vec<String> = layers_metadata.iter().map(|&(_, ref l)| l.clone()).collect();
        let vector_layers_json = Json::from_str(&format!("[{}]", vector_layers.join(","))).unwrap();
        (metadata, layers_json, vector_layers_json)
    }
    pub fn get_tilejson(&self, tileset: &str) -> String {
        let (mut metadata, _layers, vector_layers) = self.get_tilejson_infos(tileset);
        let mut obj = metadata.as_object_mut().unwrap();
        let url = Json::from_str(&format!("[\"http://127.0.0.1:6767/{}/{{z}}/{{x}}/{{y}}.pbf\"]", tileset)).unwrap();
        obj.insert("tiles".to_string(), url);
        obj.insert("vector_layers".to_string(), vector_layers);
        obj.to_json().to_string()
    }
    pub fn get_metadata(&self, tileset: &str) -> String {
        let (mut metadata, layers, vector_layers) = self.get_tilejson_infos(tileset);
        let json_str = format!(r#"
        {{
          "Layer": {},
          "vector_layers": {}
        }}"#, layers.to_string(), vector_layers.to_string());
        let metadata_vector_layers = Json::from_str(&json_str).unwrap();
        let mut obj = metadata.as_object_mut().unwrap();
        obj.insert("json".to_string(), metadata_vector_layers.to_string().to_json());
        obj.to_json().to_string()
    }
    /// Create vector tile from input at x, y, z
    pub fn tile(&self, tileset: &str, xtile: u16, ytile: u16, zoom: u16) -> vector_tile::Tile {
        let extent = self.grid.tile_extent_reverse_y(xtile, ytile, zoom);
        debug!("MVT tile request {:?}", extent);
        let mut tile = Tile::new(&extent, 4096, true);
        for layer in self.get_tileset(tileset) {
            let mut mvt_layer = tile.new_layer(layer);
            self.input.retrieve_features(&layer, &extent, zoom, |feat| {
                tile.add_feature(&mut mvt_layer, feat);
            });
            tile.add_layer(mvt_layer);
        }
        tile.mvt_tile
    }
    /// Fetch or create vector tile from input at x, y, z
    pub fn tile_cached(&self, tileset: &str, xtile: u16, ytile: u16, zoom: u16, gzip: bool) -> Vec<u8> {
        let path = format!("{}/{}/{}/{}.pbf", tileset, zoom, xtile, ytile);

        let mut tile: Option<Vec<u8>> = None;
        self.cache.read(&path, |mut f| {
            let mut data = Vec::new();
            let _ = f.read_to_end(&mut data);
            tile = Some(data);
        });
        if tile.is_some() {
            //TODO: unzip if gzip == false
            return tile.unwrap()
        }

        let mvt_tile = self.tile(tileset, xtile, ytile, zoom);

        let mut tilegz = Vec::new();
        Tile::write_gz_to(&mut tilegz, &mvt_tile);
        let _ = self.cache.write(&path, &tilegz);

        //TODO: return unzipped if gzip == false
        tilegz
    }
}

impl Tileset {
    pub fn tilesets_from_config(config: &toml::Value) -> Result<Vec<Self>, String> {
        config.lookup("tileset")
              .ok_or("Missing configuration entry [[tileset]]".to_string())
              .and_then(|tarr| tarr.as_slice().ok_or("Array type for [[tileset]] entry expected".to_string()))
              .and_then(|tilesets| {
                  Ok(tilesets.iter().map(|tileset| Tileset::from_config(tileset).unwrap()).collect())
              })
    }
}

impl Config<Tileset> for Tileset {
    fn from_config(config: &toml::Value) -> Result<Self, String> {
        let name = config.lookup("name")
                         .ok_or("Missing configuration entry name in [[tileset]]".to_string())
                         .and_then(|val| val.as_str().ok_or("tileset.name entry is not a string".to_string()))
                         .map(|v| v.to_string());
        let layers = try!(Layer::layers_from_config(config));
        name.and_then(|n|
            Ok(Tileset{name: n, layers: layers})
        )
    }
    fn gen_config() -> String {
        let mut config = String::new();
        config.push_str(&Layer::gen_config());
        config
    }
    fn gen_runtime_config(&self) -> String {
        let mut config = String::new();
        for layer in &self.layers {
            config.push_str(&layer.gen_runtime_config());
        }
        config
    }
}

impl Config<MvtService> for MvtService {
    fn from_config(config: &toml::Value) -> Result<Self, String> {
        let pg = try!(PostgisInput::from_config(config));
        let grid = try!(Grid::from_config(config));
        let tilesets = try!(Tileset::tilesets_from_config(config));
        let cache = try!(Tilecache::from_config(config));
        Ok(MvtService {input: pg, grid: grid,
                       tilesets: tilesets, cache: cache})
    }
    fn gen_config() -> String {
        let mut config = String::new();
        config.push_str(TOML_SERVICES);
        config.push_str(&Datasource::gen_config());
        config.push_str(&Grid::gen_config());
        config.push_str(&Tileset::gen_config());
        config.push_str(&Tilecache::gen_config());
        config
    }
    fn gen_runtime_config(&self) -> String {
        let mut config = String::new();
        config.push_str(TOML_SERVICES);
        config.push_str(&self.input.gen_runtime_config());
        config.push_str(&self.grid.gen_runtime_config());
        for tileset in &self.tilesets {
            config.push_str(&tileset.gen_runtime_config());
        }
        config.push_str(&self.cache.gen_runtime_config());
        config
    }
}

const TOML_SERVICES: &'static str = r#"# t-rex configuration

[services]
mvt = true
"#;

#[test]
pub fn test_tile_query() {
    use std::io::{self,Write};
    use std::env;

    let pg: PostgisInput = match env::var("DBCONN") {
        Result::Ok(val) => Some(PostgisInput {connection_url: val}),
        Result::Err(_) => { write!(&mut io::stdout(), "skipped ").unwrap(); return; }
    }.unwrap();
    let grid = Grid::web_mercator();
    let mut layer = Layer::new("points");
    layer.table_name = Some(String::from("ne_10m_populated_places"));
    layer.geometry_field = Some(String::from("wkb_geometry"));
    layer.geometry_type = Some(String::from("POINT"));
    layer.query_limit = Some(1);
    let tileset = Tileset{name: "points".to_string(), layers: vec![layer]};
    let service = MvtService {input: pg, grid: grid,
                              tilesets: vec![tileset], cache: Tilecache::Nocache(Nocache)};

    let mvt_tile = service.tile("points", 33, 22, 6);
    println!("{:#?}", mvt_tile);
    let expected = r#"Tile {
    layers: [
        Tile_Layer {
            version: Some(
                2
            ),
            name: Some("points"),
            features: [
                Tile_Feature {
                    id: None,
                    tags: [],
                    field_type: Some(
                        POINT
                    ),
                    geometry: [
                        9,
                        2504,
                        3390
                    ],
                    unknown_fields: UnknownFields {
                        fields: None
                    },
                    cached_size: Cell {
                        value: 0
                    }
                }
            ],
            keys: [],
            values: [],
            extent: Some(
                4096
            ),
            unknown_fields: UnknownFields {
                fields: None
            },
            cached_size: Cell {
                value: 0
            }
        }
    ],
    unknown_fields: UnknownFields {
        fields: None
    },
    cached_size: Cell {
        value: 0
    }
}"#;
    assert_eq!(expected, &*format!("{:#?}", mvt_tile));
}

#[test]
pub fn test_metadata() {
    use core::read_config;
    use std::io::{self,Write};
    use std::env;

    if env::var("DBCONN").is_err() {
        write!(&mut io::stdout(), "skipped ").unwrap();
        return;
    }

    let config = read_config("src/test/example.cfg").unwrap();
    let service = MvtService::from_config(&config).unwrap();
    let metadata = service.get_metadata("points");
    println!("{}", metadata);
    let format = r#""format":"pbf""#;
    assert!(metadata.contains(format));
    let jsonmeta = r#"\"vector_layers\":"#;
    assert!(metadata.contains(jsonmeta));
}

#[test]
pub fn test_gen_config() {
    let expected = r#"# t-rex configuration

[services]
mvt = true

[datasource]
type = "postgis"
# Connection specification (https://github.com/sfackler/rust-postgres#connecting)
url = "postgresql://user:pass@host:port/database"

[grid]
# Predefined grids: web_mercator, wgs84
predefined = "web_mercator"

[[tileset]]
name = "points"

[[tileset.layer]]
name = "points"
table_name = "mytable"
geometry_field = "wkb_geometry"
geometry_type = "POINT"
#fid_field = "id"
#query = "SELECT name,wkb_geometry FROM mytable"

#[cache.file]
#base = "/tmp/mvtcache"
"#;
    println!("{}", &MvtService::gen_config());
    assert_eq!(expected, &MvtService::gen_config());
}
<|endoftext|>