<commit_before>
use super::ScriptError;

pub struct Stack(Vec<Vec<u8>>);

impl Stack {

    pub fn new() -> Stack {
        Stack(Vec::new())
    }

    pub fn pop(&mut self) -> Result<Vec<u8>, ScriptError> {
        self.0.pop()
            .ok_or(ScriptError::Pop_Empty_Stack)

    }

    pub fn push(&mut self, data: Vec<u8>) -> Result<(), ScriptError> {
        self.0.push(data);
        Ok(())
    }

    pub fn pop_scriptnum(&mut self) -> Result<i64, ScriptError> {
        let bytes = try!(self.pop());

        if bytes.len() > 4 {
            return Err(ScriptError::Numeric_Overflow);
        }

        // parse bytes as little-endian
        let signed_mag: i64 = bytes.iter().enumerate().fold(0,
            |sum, (n, byte)| sum + ((*byte as i64) << (n * 8))
        );

        // signed-magnitude -> two complement
        if signed_mag < 0 {
            Ok(- signed_mag - 1)
        }
        else {
            Ok(signed_mag)
        }
    }

    pub fn push_scriptnum(&mut self, n: i64) -> Result<(), ScriptError> {

        //two-complement -> signed-magnitude
        let mut signed_mag = if n < 0 { - n - 1 } else { n };

        // create byte-array
        let mut result : Vec<u8> = Vec::with_capacity(8);
        while signed_mag != 0 && signed_mag != -1
        {
            result.push((signed_mag & 0xFF) as u8);
            signed_mag >>= 8;
        }
        self.0.push(result);
        Ok(())
    }

}

#[cfg(test)]
mod test {

    use super::*;

    #[test]
    fn test_push() {
        let mut stack = Stack::new();
        stack.push(Vec::new());

        assert_eq!(1, stack.0.len());
        assert_eq!(0, stack.0[0].len());
    }
}
<commit_msg>Cleanup<commit_after><|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("Column", inherited=False) %>

${helpers.predefined_type("column-width",
                          "length::NonNegativeLengthOrAuto",
                          "Either::Second(Auto)",
                          initial_specified_value="Either::Second(Auto)",
                          extra_prefixes="moz",
                          animation_value_type="NonNegativeLengthOrAuto",
                          servo_pref="layout.columns.enabled",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-width",
                          servo_restyle_damage="rebuild_and_reflow")}

${helpers.predefined_type(
    "column-count",
    "ColumnCount",
    "computed::ColumnCount::auto()",
    initial_specified_value="specified::ColumnCount::auto()",
    servo_pref="layout.columns.enabled",
    animation_value_type="AnimatedColumnCount",
    extra_prefixes="moz",
    spec="https://drafts.csswg.org/css-multicol/#propdef-column-count",
    servo_restyle_damage="rebuild_and_reflow",
)}

<%
# FIXME(#20498): Servo should support percentages in column-gap.
col_gap_type = "NonNegativeLengthOrPercentageOrNormal"
%>
${helpers.predefined_type(
    "column-gap",
    "length::%s" % col_gap_type,
    "Either::Second(Normal)",
    extra_prefixes="moz",
    servo_pref="layout.columns.enabled",
    animation_value_type=col_gap_type,
    spec="https://drafts.csswg.org/css-multicol/#propdef-column-gap",
    servo_restyle_damage = "reflow",
)}

${helpers.single_keyword("column-fill", "balance auto", extra_prefixes="moz",
                         products="gecko", animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-fill")}

${helpers.predefined_type("column-rule-width",
                          "BorderSideWidth",
                          "::values::computed::NonNegativeLength::new(3.)",
                          initial_specified_value="specified::BorderSideWidth::Medium",
                          computed_type="::values::computed::NonNegativeLength",
                          products="gecko",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-width",
                          animation_value_type="NonNegativeLength",
                          extra_prefixes="moz")}

// https://drafts.csswg.org/css-multicol-1/#crc
${helpers.predefined_type(
    "column-rule-color",
    "Color",
    "computed_value::T::currentcolor()",
    initial_specified_value="specified::Color::currentcolor()",
    products="gecko",
    animation_value_type="AnimatedColor",
    extra_prefixes="moz",
    ignored_when_colors_disabled=True,
    spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color",
)}

${helpers.single_keyword("column-span", "none all",
                         products="gecko", animation_value_type="discrete",
                         gecko_pref="layout.css.column-span.enabled",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-span",
                         extra_prefixes="moz")}

${helpers.single_keyword("column-rule-style",
                         "none hidden dotted dashed solid double groove ridge inset outset",
                         products="gecko", extra_prefixes="moz",
                         gecko_constant_prefix="NS_STYLE_BORDER_STYLE",
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-style")}
<commit_msg>Remove FIXME comment<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("Column", inherited=False) %>

${helpers.predefined_type("column-width",
                          "length::NonNegativeLengthOrAuto",
                          "Either::Second(Auto)",
                          initial_specified_value="Either::Second(Auto)",
                          extra_prefixes="moz",
                          animation_value_type="NonNegativeLengthOrAuto",
                          servo_pref="layout.columns.enabled",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-width",
                          servo_restyle_damage="rebuild_and_reflow")}

${helpers.predefined_type(
    "column-count",
    "ColumnCount",
    "computed::ColumnCount::auto()",
    initial_specified_value="specified::ColumnCount::auto()",
    servo_pref="layout.columns.enabled",
    animation_value_type="AnimatedColumnCount",
    extra_prefixes="moz",
    spec="https://drafts.csswg.org/css-multicol/#propdef-column-count",
    servo_restyle_damage="rebuild_and_reflow",
)}

<%
col_gap_type = "NonNegativeLengthOrPercentageOrNormal"
%>
${helpers.predefined_type(
    "column-gap",
    "length::%s" % col_gap_type,
    "Either::Second(Normal)",
    extra_prefixes="moz",
    servo_pref="layout.columns.enabled",
    animation_value_type=col_gap_type,
    spec="https://drafts.csswg.org/css-multicol/#propdef-column-gap",
    servo_restyle_damage = "reflow",
)}

${helpers.single_keyword("column-fill", "balance auto", extra_prefixes="moz",
                         products="gecko", animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-fill")}

${helpers.predefined_type("column-rule-width",
                          "BorderSideWidth",
                          "::values::computed::NonNegativeLength::new(3.)",
                          initial_specified_value="specified::BorderSideWidth::Medium",
                          computed_type="::values::computed::NonNegativeLength",
                          products="gecko",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-width",
                          animation_value_type="NonNegativeLength",
                          extra_prefixes="moz")}

// https://drafts.csswg.org/css-multicol-1/#crc
${helpers.predefined_type(
    "column-rule-color",
    "Color",
    "computed_value::T::currentcolor()",
    initial_specified_value="specified::Color::currentcolor()",
    products="gecko",
    animation_value_type="AnimatedColor",
    extra_prefixes="moz",
    ignored_when_colors_disabled=True,
    spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color",
)}

${helpers.single_keyword("column-span", "none all",
                         products="gecko", animation_value_type="discrete",
                         gecko_pref="layout.css.column-span.enabled",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-span",
                         extra_prefixes="moz")}

${helpers.single_keyword("column-rule-style",
                         "none hidden dotted dashed solid double groove ridge inset outset",
                         products="gecko", extra_prefixes="moz",
                         gecko_constant_prefix="NS_STYLE_BORDER_STYLE",
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-style")}
<|endoftext|>


<commit_before>//! Read and write Elasto Mania level files.

use std::io::{ Read };
use std::fs::File;
use byteorder::{ ByteOrder, ReadBytesExt, LittleEndian };
use super::{ Position, trim_string };

// Magic arbitrary number; signifies end-of-data. Followed by Top10 list(s).
const EOD: i32 = 0x0067103A;
// Magic arbitrary number; signifies end-of-file.
const EOF: i32 = 0x00845D52;

/// Game version.
#[derive(Debug, PartialEq)]
pub enum Version {
    Across,
    Elma
}

/// Type of object.
#[derive(Debug, PartialEq)]
pub enum ObjectType {
    Apple,
    Exit,
    Killer,
    Player
}

/// Object struct. Every level requires one `ObjectType::Player` Object and at least one `ObjectType::Exit` Object.
#[derive(Debug, PartialEq)]
pub struct Object {
    /// Position. See `Position` struct.
    pub position: Position<f64>,
    /// Type of Object, see `ObjectType`.
    pub object_type: ObjectType,
    /// Applies to `ObjectType::Apple` only.
    ///
    /// 0 = normal
    /// 1 = gravity up
    /// 2 = gravity down
    /// 3 = gravity left
    /// 4 = gravity right
    // TODO: enum with gravity
    pub gravity: i32,
    /// Applies to `ObjectType::Apple` only. Valid values are 1 to 9.
    pub animation: i32
}

/// Polygon struct.
#[derive(Debug, Default, PartialEq)]
pub struct Polygon {
    /// Grass polygon.
    pub grass: bool,
    /// Vector with all vertices, see Position struct.
    pub vertices: Vec<Position<f64>>
}

impl Polygon {
    pub fn new () -> Polygon {
        Polygon {
            grass: false,
            vertices: vec![]
        }
    }
}

/// Picture struct.
#[derive(Debug, PartialEq)]
pub struct Picture {
    /// Picture name.
    pub name: String,
    /// Texture name.
    pub texture: String,
    /// Mask name.
    pub mask: String,
    /// Position. See Position struct.
    pub position: Position<f64>,
    /// Z-distance
    pub distance: i32,
    /// Clipping.
    ///
    /// 0 = unclipped
    /// 1 = ground
    /// 2 = sky
    // TODO: make enum
    pub clip: i32
}

/// Top10 list entry struct.
#[derive(Debug)]
pub struct ListEntry {
    /// Player 1 name.
    pub name_1: String,
    /// Player 2 name.
    pub name_2: String,
    /// Time.
    pub time: i32
}

/// Level struct that contains all level information.
pub struct Level {
    /// Elma or Across level.
    pub version: Version,
    /// Raw binary data of a loaded or finalized constructed level.
    raw: Vec<u8>,
    /// Random number that links level file to replay files.
    pub link: i32,
    /// Contains four integrity checks (See calculate_integrity_sums()).
    pub integrity: [f64; 4],
    /// Level name.
    pub name: String,
    /// LGR file name.
    pub lgr: String,
    /// Ground texture name.
    pub ground: String,
    /// Sky texture name.
    pub sky: String,
    /// Vector with all polygons (See Polygon).
    pub polygons: Vec<Polygon>,
    /// Vector with all objects (See Object).
    pub objects: Vec<Object>,
    /// Vector with all pictures (See Picture).
    pub pictures: Vec<Picture>,
    /// Vector of Top10 single-player names and times.
    pub top10_single: Vec<ListEntry>,
    /// Vector of Top10 multi-player names and times.
    pub top10_multi: Vec<ListEntry>
}

impl Default for Level {
    fn default() -> Level { Level::new() }
}

impl Level {
    /// Returns a new Level struct.
    ///
    /// # Examples
    ///
    /// ```
    /// let level = elma::lev::Level::new();
    /// ```
    pub fn new () -> Level {
        Level {
            version: Version::Elma,
            raw: vec![],
            link: 0,
            integrity: [0.0f64; 4],
            name: String::new(),
            lgr: String::from("default"),
            ground: String::from("ground"),
            sky: String::from("sky"),
            polygons: vec![],
            objects: vec![],
            pictures: vec![],
            top10_single: vec![],
            top10_multi: vec![]
        }
    }

    /// Loads a level file and returns a Level struct.
    ///
    /// # Examples
    ///
    /// ```
    /// let level = elma::lev::Level::load_level("tests/test.lev");
    /// ```
    pub fn load_level (filename: &str) -> Level {
        let mut level = Level::new();
        let mut file = File::open(filename).unwrap();
        let mut buffer = vec![];
        file.read_to_end(&mut buffer).unwrap();
        level.raw = buffer;
        level.parse_level();
        level
    }

    /// Parses the raw binary data into Level struct fields.
    fn parse_level (&mut self) {
        let rem = self.raw.as_slice();

        // POT06 = Across, POT14 = Elma.
        let (version, rem) = rem.split_at(5);
        self.version = match version {
            [80, 79, 84, 49, 52] => Version::Elma,
            [80, 79, 84, 48, 54] => Version::Across,
            _ => panic!("Not a valid level file.")
        };

        // Link.
        let (_, mut rem) = rem.split_at(2); // Never used
        self.link = rem.read_i32::<LittleEndian>().unwrap();

        // Integrity checksums.
        for i in 0..4 {
            self.integrity[i] = rem.read_f64::<LittleEndian>().unwrap();
        }

        // Level name.
        let (name, rem) = rem.split_at(51);
        self.name = trim_string(name).unwrap();
        // LGR name.
        let (lgr, rem) = rem.split_at(16);
        self.lgr = trim_string(lgr).unwrap();
        // Ground texture name.
        let (ground, rem) = rem.split_at(10);
        self.ground = trim_string(ground).unwrap();
        // Sky texture name.
        let (sky, mut rem) = rem.split_at(10);
        self.sky = trim_string(sky).unwrap();

        // Polygons.
        let poly_count = (rem.read_f64::<LittleEndian>().unwrap() - 0.4643643).round() as usize;
        for _ in 0..poly_count {
            let grass = rem.read_i32::<LittleEndian>().unwrap() > 0;
            let vertex_count = rem.read_i32::<LittleEndian>().unwrap();
            let mut vertices: Vec<Position<f64>> = vec![];
            for _ in 0..vertex_count {
                let x = rem.read_f64::<LittleEndian>().unwrap();
                let y = rem.read_f64::<LittleEndian>().unwrap();
                vertices.push(Position {
                    x: x,
                    y: y
                });
            }
            self.polygons.push(Polygon {
                grass: grass,
                vertices: vertices
            });
        }

        // Objects.
        let object_count = (rem.read_f64::<LittleEndian>().unwrap() - 0.4643643).round() as usize;
        for _ in 0..object_count {
            let x = rem.read_f64::<LittleEndian>().unwrap();
            let y = rem.read_f64::<LittleEndian>().unwrap();
            let position = Position { x: x, y: y };
            let object_type = match rem.read_i32::<LittleEndian>().unwrap() {
                1 => ObjectType::Exit,
                2 => ObjectType::Apple,
                3 => ObjectType::Killer,
                4 => ObjectType::Player,
                _ => panic!("Not a valid object type")
            };
            let gravity = rem.read_i32::<LittleEndian>().unwrap();
            let animation = rem.read_i32::<LittleEndian>().unwrap() + 1;

            self.objects.push(Object {
                position: position,
                object_type: object_type,
                gravity: gravity,
                animation: animation
            });
        }

        // Pictures.
        let picture_count = (rem.read_f64::<LittleEndian>().unwrap() - 0.2345672).round() as usize;
        for _ in 0..picture_count {
            let (name, temp_rem) = rem.split_at(10);
            let name = trim_string(name).unwrap();
            let (texture, temp_rem) = temp_rem.split_at(10);
            let texture = trim_string(texture).unwrap();
            let (mask, temp_rem) = temp_rem.split_at(10);
            rem = temp_rem;
            let mask = trim_string(mask).unwrap();
            let x = rem.read_f64::<LittleEndian>().unwrap();
            let y = rem.read_f64::<LittleEndian>().unwrap();
            let distance = rem.read_i32::<LittleEndian>().unwrap();
            let clip = rem.read_i32::<LittleEndian>().unwrap();

            self.pictures.push(Picture {
                name: name,
                texture: texture,
                mask: mask,
                position: Position { x: x, y: y },
                distance: distance,
                clip: clip
            });
        }

        // EOD marker expected at this point.
        let expected = rem.read_i32::<LittleEndian>().unwrap();
        if expected != EOD { panic!("EOD marker mismatch: x0{:x} != x0{:x}", expected, EOD); }

        // First decrypt the top10 blocks.
        let (mut top10, mut rem) = rem.split_at(688);
        let decrypted_top10_data = crypt_top10(top10);

        // Single-player list.
        let single = &decrypted_top10_data[0..344];
        self.top10_single = parse_top10(single);

        // Multi-player list.
        let multi = &decrypted_top10_data[344..688];
        self.top10_multi = parse_top10(multi);

        // EOF marker expected at this point.
        let expected = rem.read_i32::<LittleEndian>().unwrap();
        if expected != EOF { panic!("EOF marker mismatch: x0{:x} != x0{:x}", expected, EOF); }
    }

    /// Combines the Level struct fields to generate the raw binary data,
    /// and calculate integrity sums.
    fn update (&self) {
        // TODO: convert
        self.calculate_integrity_sums();
    }

    fn calculate_integrity_sums (&self) {
        // TODO: do that
    }

    /// Converts all struct fields into raw binary form and returns it.
    pub fn get_raw (self) -> Vec<u8> {
        self.update();
        self.raw
    }

    /// Saves level as a file.
    pub fn save_lev (self, filename: &str) {
        self.update();
        // let file = File::create(&filename).unwrap();
        // TODO: write stuff.
    }
}

/// Decrypt and encrypt top10 list data. Same algorithm for both.
pub fn crypt_top10 (top10: &[u8]) -> &[u8] {
    // Who knows
    let mut ebp8: i16 = 0x15;
    let mut ebp10: i16 = 0x2637;

    for mut t in top10.iter_mut().take(688) {
        *t ^= (ebp8 & 0xFF) as u8;
        ebp10 = ebp10.wrapping_add((ebp8.wrapping_rem(0xD3D)).wrapping_mul(0xD3D));
        ebp8 = ebp10.wrapping_mul(0x1F).wrapping_add(0xD3D);
    }

    top10
}

/// Parse top10 lists and return a vector of `ListEntry`s
pub fn parse_top10 (top10: &[u8]) -> Vec<ListEntry> {
    let mut list: Vec<ListEntry> = vec![];
    let times = LittleEndian::read_i32(&top10[0..4]);
    for n in 0..times {
        let time_offset = (4 + n * 4) as usize;
        let time_end = time_offset + 4;
        let name_1_offset = (44 + n * 15) as usize;
        let name_1_end = name_1_offset + 15;
        let name_2_offset = (194 + n * 15) as usize;
        let name_2_end = name_2_offset + 15;
        // All of this pains me even though I don't understand it...
        let name_1 = &top10[name_1_offset..name_1_end];
        let name_2 = &top10[name_2_offset..name_2_end];
        list.push(ListEntry {
            time: LittleEndian::read_i32(&top10[time_offset..time_end]),
            name_1: trim_string(name_1).unwrap(),
            name_2: trim_string(name_2).unwrap()
        });
    }
    list
}
<commit_msg>Fix crypt_top10 function, introduce more errors<commit_after>//! Read and write Elasto Mania level files.

use std::io::{ Read };
use std::fs::File;
use byteorder::{ ByteOrder, ReadBytesExt, LittleEndian };
use super::{ Position, trim_string };

// Magic arbitrary number; signifies end-of-data. Followed by Top10 list(s).
const EOD: i32 = 0x0067103A;
// Magic arbitrary number; signifies end-of-file.
const EOF: i32 = 0x00845D52;

/// Game version.
#[derive(Debug, PartialEq)]
pub enum Version {
    Across,
    Elma
}

/// Type of object.
#[derive(Debug, PartialEq)]
pub enum ObjectType {
    Apple,
    Exit,
    Killer,
    Player
}

/// Object struct. Every level requires one `ObjectType::Player` Object and at least one `ObjectType::Exit` Object.
#[derive(Debug, PartialEq)]
pub struct Object {
    /// Position. See `Position` struct.
    pub position: Position<f64>,
    /// Type of Object, see `ObjectType`.
    pub object_type: ObjectType,
    /// Applies to `ObjectType::Apple` only.
    ///
    /// 0 = normal
    /// 1 = gravity up
    /// 2 = gravity down
    /// 3 = gravity left
    /// 4 = gravity right
    // TODO: enum with gravity
    pub gravity: i32,
    /// Applies to `ObjectType::Apple` only. Valid values are 1 to 9.
    pub animation: i32
}

/// Polygon struct.
#[derive(Debug, Default, PartialEq)]
pub struct Polygon {
    /// Grass polygon.
    pub grass: bool,
    /// Vector with all vertices, see Position struct.
    pub vertices: Vec<Position<f64>>
}

impl Polygon {
    pub fn new () -> Polygon {
        Polygon {
            grass: false,
            vertices: vec![]
        }
    }
}

/// Picture struct.
#[derive(Debug, PartialEq)]
pub struct Picture {
    /// Picture name.
    pub name: String,
    /// Texture name.
    pub texture: String,
    /// Mask name.
    pub mask: String,
    /// Position. See Position struct.
    pub position: Position<f64>,
    /// Z-distance
    pub distance: i32,
    /// Clipping.
    ///
    /// 0 = unclipped
    /// 1 = ground
    /// 2 = sky
    // TODO: make enum
    pub clip: i32
}

/// Top10 list entry struct.
#[derive(Debug)]
pub struct ListEntry {
    /// Player 1 name.
    pub name_1: String,
    /// Player 2 name.
    pub name_2: String,
    /// Time.
    pub time: i32
}

/// Level struct that contains all level information.
pub struct Level {
    /// Elma or Across level.
    pub version: Version,
    /// Raw binary data of a loaded or finalized constructed level.
    raw: Vec<u8>,
    /// Random number that links level file to replay files.
    pub link: i32,
    /// Contains four integrity checks (See calculate_integrity_sums()).
    pub integrity: [f64; 4],
    /// Level name.
    pub name: String,
    /// LGR file name.
    pub lgr: String,
    /// Ground texture name.
    pub ground: String,
    /// Sky texture name.
    pub sky: String,
    /// Vector with all polygons (See Polygon).
    pub polygons: Vec<Polygon>,
    /// Vector with all objects (See Object).
    pub objects: Vec<Object>,
    /// Vector with all pictures (See Picture).
    pub pictures: Vec<Picture>,
    /// Vector of Top10 single-player names and times.
    pub top10_single: Vec<ListEntry>,
    /// Vector of Top10 multi-player names and times.
    pub top10_multi: Vec<ListEntry>
}

impl Default for Level {
    fn default() -> Level { Level::new() }
}

impl Level {
    /// Returns a new Level struct.
    ///
    /// # Examples
    ///
    /// ```
    /// let level = elma::lev::Level::new();
    /// ```
    pub fn new () -> Level {
        Level {
            version: Version::Elma,
            raw: vec![],
            link: 0,
            integrity: [0.0f64; 4],
            name: String::new(),
            lgr: String::from("default"),
            ground: String::from("ground"),
            sky: String::from("sky"),
            polygons: vec![],
            objects: vec![],
            pictures: vec![],
            top10_single: vec![],
            top10_multi: vec![]
        }
    }

    /// Loads a level file and returns a Level struct.
    ///
    /// # Examples
    ///
    /// ```
    /// let level = elma::lev::Level::load_level("tests/test.lev");
    /// ```
    pub fn load_level (filename: &str) -> Level {
        let mut level = Level::new();
        let mut file = File::open(filename).unwrap();
        let mut buffer = vec![];
        file.read_to_end(&mut buffer).unwrap();
        level.raw = buffer;
        level.parse_level();
        level
    }

    /// Parses the raw binary data into Level struct fields.
    fn parse_level (&mut self) {
        let rem = self.raw.as_mut_slice();

        // POT06 = Across, POT14 = Elma.
        let (version, rem) = rem.split_at_mut(5);
        self.version = match version {
            [80, 79, 84, 49, 52] => Version::Elma,
            [80, 79, 84, 48, 54] => Version::Across,
            _ => panic!("Not a valid level file.")
        };

        // Link.
        let (_, mut rem) = rem.split_at_mut(2); // Never used
        self.link = (&*rem).read_i32::<LittleEndian>().unwrap();

        // Integrity checksums.
        for i in 0..4 {
            self.integrity[i] = (&*rem).read_f64::<LittleEndian>().unwrap();
        }

        // Level name.
        let (name, rem) = rem.split_at_mut(51);
        self.name = trim_string(name).unwrap();
        // LGR name.
        let (lgr, rem) = rem.split_at_mut(16);
        self.lgr = trim_string(lgr).unwrap();
        // Ground texture name.
        let (ground, rem) = rem.split_at_mut(10);
        self.ground = trim_string(ground).unwrap();
        // Sky texture name.
        let (sky, mut rem) = rem.split_at_mut(10);
        self.sky = trim_string(sky).unwrap();

        // Polygons.
        let poly_count = ((&*rem).read_f64::<LittleEndian>().unwrap() - 0.4643643).round() as usize;
        for _ in 0..poly_count {
            let grass = (&*rem).read_i32::<LittleEndian>().unwrap() > 0;
            let vertex_count = (&*rem).read_i32::<LittleEndian>().unwrap();
            let mut vertices: Vec<Position<f64>> = vec![];
            for _ in 0..vertex_count {
                let x = (&*rem).read_f64::<LittleEndian>().unwrap();
                let y = (&*rem).read_f64::<LittleEndian>().unwrap();
                vertices.push(Position {
                    x: x,
                    y: y
                });
            }
            self.polygons.push(Polygon {
                grass: grass,
                vertices: vertices
            });
        }

        // Objects.
        let object_count = ((&*rem).read_f64::<LittleEndian>().unwrap() - 0.4643643).round() as usize;
        for _ in 0..object_count {
            let x = (&*rem).read_f64::<LittleEndian>().unwrap();
            let y = (&*rem).read_f64::<LittleEndian>().unwrap();
            let position = Position { x: x, y: y };
            let object_type = match (&*rem).read_i32::<LittleEndian>().unwrap() {
                1 => ObjectType::Exit,
                2 => ObjectType::Apple,
                3 => ObjectType::Killer,
                4 => ObjectType::Player,
                _ => panic!("Not a valid object type")
            };
            let gravity = (&*rem).read_i32::<LittleEndian>().unwrap();
            let animation = (&*rem).read_i32::<LittleEndian>().unwrap() + 1;

            self.objects.push(Object {
                position: position,
                object_type: object_type,
                gravity: gravity,
                animation: animation
            });
        }

        // Pictures.
        let picture_count = ((&*rem).read_f64::<LittleEndian>().unwrap() - 0.2345672).round() as usize;
        for _ in 0..picture_count {
            let (name, temp_rem) = rem.split_at_mut(10);
            let name = trim_string(name).unwrap();
            let (texture, temp_rem) = temp_rem.split_at_mut(10);
            let texture = trim_string(texture).unwrap();
            let (mask, temp_rem) = temp_rem.split_at_mut(10);
            rem = temp_rem;
            let mask = trim_string(mask).unwrap();
            let x = (&*rem).read_f64::<LittleEndian>().unwrap();
            let y = (&*rem).read_f64::<LittleEndian>().unwrap();
            let distance = (&*rem).read_i32::<LittleEndian>().unwrap();
            let clip = (&*rem).read_i32::<LittleEndian>().unwrap();

            self.pictures.push(Picture {
                name: name,
                texture: texture,
                mask: mask,
                position: Position { x: x, y: y },
                distance: distance,
                clip: clip
            });
        }

        // EOD marker expected at this point.
        let expected = (&*rem).read_i32::<LittleEndian>().unwrap();
        if expected != EOD { panic!("EOD marker mismatch: x0{:x} != x0{:x}", expected, EOD); }

        // First decrypt the top10 blocks.
        let (top10, rem) = rem.split_at_mut(688);
        let decrypted_top10_data = crypt_top10(top10);

        // Single-player list.
        let single = &decrypted_top10_data[0..344];
        self.top10_single = parse_top10(single);

        // Multi-player list.
        let multi = &decrypted_top10_data[344..688];
        self.top10_multi = parse_top10(multi);

        // EOF marker expected at this point.
        let expected = (&*rem).read_i32::<LittleEndian>().unwrap();
        if expected != EOF { panic!("EOF marker mismatch: x0{:x} != x0{:x}", expected, EOF); }
    }

    /// Combines the Level struct fields to generate the raw binary data,
    /// and calculate integrity sums.
    fn update (&self) {
        // TODO: convert
        self.calculate_integrity_sums();
    }

    fn calculate_integrity_sums (&self) {
        // TODO: do that
    }

    /// Converts all struct fields into raw binary form and returns it.
    pub fn get_raw (self) -> Vec<u8> {
        self.update();
        self.raw
    }

    /// Saves level as a file.
    pub fn save_lev (self, filename: &str) {
        self.update();
        // let file = File::create(&filename).unwrap();
        // TODO: write stuff.
    }
}

/// Decrypt and encrypt top10 list data. Same algorithm for both.
pub fn crypt_top10 (top10: &mut [u8]) -> &[u8] {
    // Who knows
    let mut ebp8: i16 = 0x15;
    let mut ebp10: i16 = 0x2637;

    for mut t in top10.iter_mut().take(688) {
        *t ^= (ebp8 & 0xFF) as u8;
        ebp10 = ebp10.wrapping_add((ebp8.wrapping_rem(0xD3D)).wrapping_mul(0xD3D));
        ebp8 = ebp10.wrapping_mul(0x1F).wrapping_add(0xD3D);
    }

    top10
}

/// Parse top10 lists and return a vector of `ListEntry`s
pub fn parse_top10 (top10: &[u8]) -> Vec<ListEntry> {
    let mut list: Vec<ListEntry> = vec![];
    let times = LittleEndian::read_i32(&top10[0..4]);
    for n in 0..times {
        let time_offset = (4 + n * 4) as usize;
        let time_end = time_offset + 4;
        let name_1_offset = (44 + n * 15) as usize;
        let name_1_end = name_1_offset + 15;
        let name_2_offset = (194 + n * 15) as usize;
        let name_2_end = name_2_offset + 15;
        // All of this pains me even though I don't understand it...
        let name_1 = &top10[name_1_offset..name_1_end];
        let name_2 = &top10[name_2_offset..name_2_end];
        list.push(ListEntry {
            time: LittleEndian::read_i32(&top10[time_offset..time_end]),
            name_1: trim_string(name_1).unwrap(),
            name_2: trim_string(name_2).unwrap()
        });
    }
    list
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("Column", inherited=False) %>

${helpers.predefined_type("column-width",
                          "length::LengthOrAuto",
                          "Either::Second(Auto)",
                          initial_specified_value="Either::Second(Auto)",
                          parse_method="parse_non_negative_length",
                          extra_prefixes="moz",
                          animation_type="normal",
                          experimental=True,
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-width")}

${helpers.predefined_type("column-count",
                          "IntegerOrAuto",
                          "Either::Second(Auto)",
                          parse_method="parse_positive",
                          initial_specified_value="Either::Second(Auto)",
                          experimental="True",
                          animation_type="none",
                          extra_prefixes="moz",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-count")}

${helpers.predefined_type("column-gap",
                          "length::LengthOrNormal",
                          "Either::Second(Normal)",
                          parse_method='parse_non_negative_length',
                          extra_prefixes="moz",
                          experimental=True,
                          animation_type="normal",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-gap")}

${helpers.single_keyword("column-fill", "balance auto", extra_prefixes="moz",
                         products="gecko", animation_type="none",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-fill")}

// https://drafts.csswg.org/css-multicol-1/#propdef-column-rule-width
<%helpers:longhand name="column-rule-width" products="gecko" animation_type="normal" extra_prefixes="moz"
                   spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-width">
    use app_units::Au;
    use std::fmt;
    use style_traits::ToCss;
    use values::HasViewportPercentage;
    use values::specified::BorderWidth;

    pub mod computed_value {
        use app_units::Au;
        pub type T = Au;
    }

    pub type SpecifiedValue = BorderWidth;

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        Au::from_px(3) // medium
    }

    #[inline]
    pub fn get_initial_specified_value() -> SpecifiedValue {
        BorderWidth::Medium
    }

    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
        BorderWidth::parse(context, input)
    }
</%helpers:longhand>

// https://drafts.csswg.org/css-multicol-1/#crc
${helpers.predefined_type("column-rule-color", "CSSColor",
                          "::cssparser::Color::CurrentColor",
                          initial_specified_value="specified::CSSColor::currentcolor()",
                          products="gecko", animation_type="normal", extra_prefixes="moz",
                          complex_color=True, need_clone=True,
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color")}

// It's not implemented in servo or gecko yet.
${helpers.single_keyword("column-span", "none all",
                         products="none", animation_type="none",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-span")}

${helpers.single_keyword("column-rule-style",
                         "none hidden dotted dashed solid double groove ridge inset outset",
                         products="gecko", extra_prefixes="moz",
                         gecko_constant_prefix="NS_STYLE_BORDER_STYLE",
                         animation_type="none",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-style")}
<commit_msg>Auto merge of #16536 - BorisChiou:stylo/animation/column_count, r=Manishearth<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("Column", inherited=False) %>

${helpers.predefined_type("column-width",
                          "length::LengthOrAuto",
                          "Either::Second(Auto)",
                          initial_specified_value="Either::Second(Auto)",
                          parse_method="parse_non_negative_length",
                          extra_prefixes="moz",
                          animation_type="normal",
                          experimental=True,
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-width")}

${helpers.predefined_type("column-count",
                          "IntegerOrAuto",
                          "Either::Second(Auto)",
                          parse_method="parse_positive",
                          initial_specified_value="Either::Second(Auto)",
                          experimental="True",
                          animation_type="normal",
                          extra_prefixes="moz",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-count")}

${helpers.predefined_type("column-gap",
                          "length::LengthOrNormal",
                          "Either::Second(Normal)",
                          parse_method='parse_non_negative_length',
                          extra_prefixes="moz",
                          experimental=True,
                          animation_type="normal",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-gap")}

${helpers.single_keyword("column-fill", "balance auto", extra_prefixes="moz",
                         products="gecko", animation_type="none",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-fill")}

// https://drafts.csswg.org/css-multicol-1/#propdef-column-rule-width
<%helpers:longhand name="column-rule-width" products="gecko" animation_type="normal" extra_prefixes="moz"
                   spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-width">
    use app_units::Au;
    use std::fmt;
    use style_traits::ToCss;
    use values::HasViewportPercentage;
    use values::specified::BorderWidth;

    pub mod computed_value {
        use app_units::Au;
        pub type T = Au;
    }

    pub type SpecifiedValue = BorderWidth;

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        Au::from_px(3) // medium
    }

    #[inline]
    pub fn get_initial_specified_value() -> SpecifiedValue {
        BorderWidth::Medium
    }

    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
        BorderWidth::parse(context, input)
    }
</%helpers:longhand>

// https://drafts.csswg.org/css-multicol-1/#crc
${helpers.predefined_type("column-rule-color", "CSSColor",
                          "::cssparser::Color::CurrentColor",
                          initial_specified_value="specified::CSSColor::currentcolor()",
                          products="gecko", animation_type="normal", extra_prefixes="moz",
                          complex_color=True, need_clone=True,
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color")}

// It's not implemented in servo or gecko yet.
${helpers.single_keyword("column-span", "none all",
                         products="none", animation_type="none",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-span")}

${helpers.single_keyword("column-rule-style",
                         "none hidden dotted dashed solid double groove ridge inset outset",
                         products="gecko", extra_prefixes="moz",
                         gecko_constant_prefix="NS_STYLE_BORDER_STYLE",
                         animation_type="none",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-style")}
<|endoftext|>


<commit_before>use serde::de::{Deserialize, Deserializer, Error};

use types::*;

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Message {
    pub id: Integer,
    pub from: Option<User>,
    pub date: Integer,
    pub chat: Chat,
    pub forward: Option<Forward>,
    pub reply_to_message: Option<Box<Message>>,
    pub edit_date: Option<Integer>,
    pub caption: Option<String>,
    pub kind: MessageKind,
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Forward {
    pub date: Integer,
    pub from: ForwardFrom,
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum ForwardFrom {
    User {
        user: User,
    },
    Channel {
        channel: Channel,
        message_id: Integer
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum MessageKind {
    Text {
        data: String,
        entities: Vec<MessageEntity>,
    },
    Audio {
        data: Audio,
    },
    Document {
        data: Document,
    },
    Photo {
        data: Vec<PhotoSize>,
    },
    Sticker {
        data: Sticker,
    },
    Video {
        data: Video,
    },
    Voice {
        data: Voice,
    },
    Contact {
        data: Contact,
    },
    Location {
        data: Location,
    },
    Venue {
        data: Venue,
    },
    NewChatMember {
        data: User,
    },
    LeftChatMember {
        data: User,
    },
    NewChatTitle {
        data: String,
    },
    NewChatPhoto {
        data: PhotoSize,
    },
    DeleteChatPhoto,
    GroupChatCreated,
    SupergroupChatCreated,
    ChannelChatCreated,
    MigrateToChatId {
        data: Integer,
    },
    MigrateFromChatId {
        data: Integer,
    },
    PinnedMessage {
        data: Box<Message>,
    },
    #[doc(hidden)]
    Unknown {
        raw: RawMessage
    }
}

impl Deserialize for Message {  // TODO(knsd): Remove .clone()
    fn deserialize<D>(deserializer: D) -> Result<Message, D::Error> where D: Deserializer {
        let raw: RawMessage = Deserialize::deserialize(deserializer)?;

        let id = raw.message_id;
        let from = raw.from.clone();
        let date = raw.date;
        let chat = raw.chat.clone();
        let reply_to_message = raw.reply_to_message.clone();
        let edit_date = raw.edit_date;
        let caption = raw.caption.clone();

        let forward = match (raw.forward_date, &raw.forward_from,
                             &raw.forward_from_chat, raw.forward_from_message_id) {
            (None, &None, &None, None) => None,
            (Some(date), &Some(ref from), &None, None) => {
                Some(Forward {
                    date: date,
                    from: ForwardFrom::User {
                        user: from.clone(),
                    },
                })
            },
            (Some(date), &None, &Some(Chat::Channel(ref channel)), Some(message_id)) => {
                Some(Forward {
                    date: date,
                    from: ForwardFrom::Channel {
                        channel: channel.clone(),
                        message_id: message_id,
                    },
                })
            },
            _ => {
                return Err(D::Error::custom("invalid forward fields combination"))
            }
        };

        let make_message = |kind| {
            Ok(Message {
                id: id,
                from: from,
                date: date,
                chat: chat,
                forward: forward,
                reply_to_message: reply_to_message,
                edit_date: edit_date,
                caption: caption,
                kind: kind,
            })
        };

        macro_rules! maybe_field {
            ($name:ident, $variant:ident) => {{
                if let Some(val) = raw.$name {
                    return make_message(MessageKind::$variant {
                        data: val
                    })
                }
            }}
        }

        macro_rules! maybe_true_field {
            ($name:ident, $variant:ident) => {{
                if let Some(True) = raw.$name {
                    return make_message(MessageKind::$variant)
                }
            }}
        }

        if let Some(text) = raw.text {
            let entities = raw.entities.unwrap_or_else(Vec::new);
            return make_message(MessageKind::Text {
                data: text,
                entities: entities,
            })
        }

        maybe_field!(audio, Audio);
        maybe_field!(document, Document);
        maybe_field!(photo, Photo);
        maybe_field!(sticker, Sticker);
        maybe_field!(video, Video);
        maybe_field!(voice, Voice);
        maybe_field!(contact, Contact);
        maybe_field!(location, Location);
        maybe_field!(venue, Venue);
        maybe_field!(new_chat_member, NewChatMember);
        maybe_field!(left_chat_member, LeftChatMember);
        maybe_field!(new_chat_title, NewChatTitle);
        maybe_field!(new_chat_photo, NewChatPhoto);
        maybe_true_field!(delete_chat_photo, DeleteChatPhoto);
        maybe_true_field!(delete_chat_photo, DeleteChatPhoto);
        maybe_true_field!(group_chat_created, GroupChatCreated);
        maybe_true_field!(supergroup_chat_created, SupergroupChatCreated);
        maybe_true_field!(channel_chat_created, ChannelChatCreated);
        maybe_field!(migrate_to_chat_id, MigrateToChatId);
        maybe_field!(migrate_from_chat_id, MigrateFromChatId);
        maybe_field!(pinned_message, PinnedMessage);

        make_message(MessageKind::Unknown {
            raw: raw,
        })
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct RawMessage {
    pub message_id: Integer,
    pub from: Option<User>,
    pub date: Integer,
    pub chat: Chat,
    pub forward_from: Option<User>,
    pub forward_from_chat: Option<Chat>,
    pub forward_from_message_id: Option<Integer>,
    pub forward_date: Option<Integer>,
    pub reply_to_message: Option<Box<Message>>,
    pub edit_date: Option<Integer>,
    pub text: Option<String>,
    pub entities: Option<Vec<MessageEntity>>,
    pub audio: Option<Audio>,
    pub document: Option<Document>,
//    pub game: Option<Game>,
    pub photo: Option<Vec<PhotoSize>>,
    pub sticker: Option<Sticker>,
    pub video: Option<Video>,
    pub voice: Option<Voice>,
    pub caption: Option<String>,
    pub contact: Option<Contact>,
    pub location: Option<Location>,
    pub venue: Option<Venue>,
    pub new_chat_member: Option<User>,
    pub left_chat_member: Option<User>,
    pub new_chat_title: Option<String>,
    pub new_chat_photo: Option<PhotoSize>,
    pub delete_chat_photo: Option<True>,
    pub group_chat_created: Option<True>,
    pub supergroup_chat_created: Option<True>,
    pub channel_chat_created: Option<True>,
    pub migrate_to_chat_id: Option<Integer>,
    pub migrate_from_chat_id: Option<Integer>,
    pub pinned_message: Option<Box<Message>>,
}

/// This object represents one special entity in a text message.
/// For example, hashtags, usernames, URLs, etc.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct MessageEntity {
    /// Offset in UTF-16 code units to the start of the entity
    offset: Integer,
    /// Length of the entity in UTF-16 code units
    length: Integer,
    /// Kind of the entity.
    kind: MessageEntityKind,
}

/// Kind of the entity.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum MessageEntityKind {
    Mention,
    Hashtag,
    BotCommand,
    Url,
    Email,
    Bold,
    Italic,
    Code,
    Pre,
    TextLink(String), // TODO(knsd) URL?
    TextMention(User),
    #[doc(hidden)]
    Unknown(RawMessageEntity),
}

impl Deserialize for MessageEntity {
    fn deserialize<D>(deserializer: D) -> Result<MessageEntity, D::Error> where D: Deserializer {
        use self::MessageEntityKind::*;

        let raw: RawMessageEntity = Deserialize::deserialize(deserializer)?;

        let offset = raw.offset;
        let length = raw.length;

        macro_rules! required_field {
            ($name:ident) => {{
                match raw.$name {
                    Some(val) => val,
                    None => return Err(D::Error::missing_field(stringify!($name)))
                }
            }}
        }

        let kind = match raw.type_.as_str() {
            "mention" => Mention,
            "hashtag" => Hashtag,
            "bot_command" => BotCommand,
            "url" => Url,
            "email" => Email,
            "bold" => Bold,
            "italic" => Italic,
            "code" => Code,
            "pre" => Pre,
            "text_link" => TextLink(required_field!(url)),
            "text_mention" => TextMention(required_field!(user)),
            _ => Unknown(raw),
        };

        Ok(MessageEntity {
            offset: offset,
            length: length,
            kind: kind,
        })
    }
}

/// This object represents one special entity in a text message.
/// For example, hashtags, usernames, URLs, etc. Directly mapped.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct RawMessageEntity {
    /// Type of the entity. Can be mention (@username), hashtag, bot_command, url, email,
    /// bold (bold text), italic (italic text), code (monowidth string), pre (monowidth block),
    /// text_link (for clickable text URLs), text_mention (for users without usernames).
    #[serde(rename="type")]
    pub type_: String,
    /// Offset in UTF-16 code units to the start of the entity.
    pub offset: Integer,
    /// Length of the entity in UTF-16 code units.
    pub length: Integer,
    /// For “text_link” only, url that will be opened after user taps on the text.
    pub url: Option<String>,
    /// For “text_mention” only, the mentioned user.
    pub user: Option<User>,
}

/// This object represents one size of a photo or a file / sticker thumbnail.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct PhotoSize {
    /// Unique identifier for this file.
    pub file_id: String,
    /// Photo width.
    pub width: Integer,
    /// Photo height.
    pub height: Integer,
    /// File size.
    pub file_size: Option<Integer>,
}

/// This object represents an audio file to be treated as music by the Telegram clients.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct Audio {
    /// Unique identifier for this file.
    pub file_id: String,
    /// Duration of the audio in seconds as defined by sender.
    pub duration: Integer,
    /// Performer of the audio as defined by sender or by audio tags.
    pub performer: Option<String>,
    /// Title of the audio as defined by sender or by audio tags.
    pub title: Option<String>,
    /// MIME type of the file as defined by sender.
    pub mime_type: Option<String>,
    /// File size.
    pub file_size: Option<Integer>,
}

/// This object represents a general file (as opposed to photos, voice messages and audio files).
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct Document {
    /// Unique file identifier.
    pub file_id: String,
    /// Document thumbnail as defined by sender.
    pub thumb: Option<PhotoSize>,
    /// Original filename as defined by sender.
    pub file_name: Option<String>,
    /// MIME type of the file as defined by sender.
    pub mime_type: Option<String>,
    /// File size.
    pub file_size: Option<Integer>,
}

/// This object represents a sticker.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct Sticker {
    /// Unique identifier for this file.
    pub file_id: String,
    /// Sticker width.
    pub width: Integer,
    /// Sticker height.
    pub height: Integer,
    /// Sticker thumbnail in .webp or .jpg format.
    pub thumb: Option<PhotoSize>,
    /// Emoji associated with the sticker.
    pub emoji: Option<String>,
    /// File size.
    pub file_size: Option<Integer>,
}

/// This object represents a video file.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct Video {
    /// Unique identifier for this file.
    pub file_id: String,
    /// Video width as defined by sender.
    pub width: Integer,
    /// Video height as defined by sender.
    pub height: Integer,
    /// Duration of the video in seconds as defined by sender.
    pub duration: Integer,
    /// Video thumbnail.
    pub thumb: Option<PhotoSize>,
    /// Mime type of a file as defined by sender.
    pub mime_type: Option<String>,
    /// File size.
    pub file_size: Option<Integer>,
}

/// This object represents a voice note.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct Voice {
    /// Unique identifier for this file.
    pub file_id: String,
    /// Duration of the audio in seconds as defined by sender.
    pub duration: Integer,
    /// MIME type of the file as defined by sender.
    pub mime_type: Option<String>,
    /// File size.
    pub file_size: Option<Integer>,
}

/// This object represents a phone contact.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct Contact {
    /// Contact's phone number.
    pub phone_number: String,
    /// Contact's first name.
    pub first_name: String,
    /// Contact's last name.
    pub last_name: Option<String>,
    /// Contact's user identifier in Telegram.
    pub user_id: Option<Integer>,
}

/// This object represents a point on the map.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct Location {
    /// Longitude as defined by sender.
    pub longitude: Float,
    /// Latitude as defined by sender.
    pub latitude: Float,
}

/// This object represents a venue.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct Venue {
    /// Venue location.
    pub location: Location,
    /// Name of the venue.
    pub title: String,
    /// Address of the venue.
    pub address: String,
    /// Foursquare identifier of the venue.
    pub foursquare_id: Option<String>,
}

/// This object represent a user's profile pictures.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct UserProfilePhotos {
    /// Total number of profile pictures the target user has.
    pub total_count: Integer,
    /// Requested profile pictures (in up to 4 sizes each).
    pub photos: Vec<Vec<PhotoSize>>,
}

/// This object represents a file ready to be downloaded.
/// The file can be downloaded via the link https://api.telegram.org/file/bot<token>/<file_path>.
/// It is guaranteed that the link will be valid for at least 1 hour.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct File {
    /// Unique identifier for this file.
    pub file_id: String,
    /// File size, if known.
    pub file_size: Option<Integer>,
    /// File path. Use https://api.telegram.org/file/bot<token>/<file_path> to get the file.
    pub file_path: Option<String>,
}
<commit_msg>docs: document some message types<commit_after>use serde::de::{Deserialize, Deserializer, Error};

use types::*;

/// This object represents a message.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Message {
    /// Unique message identifier inside this chat.
    pub id: Integer,
    /// Sender, can be empty for messages sent to channels.
    pub from: Option<User>,
    /// Date the message was sent in Unix time.
    pub date: Integer,
    /// Conversation the message belongs to.
    pub chat: Chat,
    /// Information about the original message.
    pub forward: Option<Forward>,
    /// For replies, the original message. Note that the Message object in this field will not
    /// contain further reply_to_message fields even if it itself is a reply.
    pub reply_to_message: Option<Box<Message>>,
    /// Date the message was last edited in Unix time.
    pub edit_date: Option<Integer>,
    pub caption: Option<String>,  // TODO(knsd): move to document, photo & video variants
    /// Kind of the message.
    pub kind: MessageKind,
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Forward {
    /// Date the original message was sent in Unix time
    pub date: Integer,
    /// Sender of the original message.
    pub from: ForwardFrom,
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum ForwardFrom {
    /// Sender of the original message.
    User {
        /// Sender of the original message.
        user: User,
    },
    /// For messages forwarded from a channel, information about the original channel.
    Channel {
        /// Original channel.
        channel: Channel,
        /// Identifier of the original message in the channel
        message_id: Integer
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum MessageKind {
    Text {
        data: String,
        entities: Vec<MessageEntity>,
    },
    Audio {
        data: Audio,
    },
    Document {
        data: Document,
    },
    Photo {
        data: Vec<PhotoSize>,
    },
    Sticker {
        data: Sticker,
    },
    Video {
        data: Video,
    },
    Voice {
        data: Voice,
    },
    Contact {
        data: Contact,
    },
    Location {
        data: Location,
    },
    Venue {
        data: Venue,
    },
    NewChatMember {
        data: User,
    },
    LeftChatMember {
        data: User,
    },
    NewChatTitle {
        data: String,
    },
    NewChatPhoto {
        data: PhotoSize,
    },
    DeleteChatPhoto,
    GroupChatCreated,
    SupergroupChatCreated,
    ChannelChatCreated,
    MigrateToChatId {
        data: Integer,
    },
    MigrateFromChatId {
        data: Integer,
    },
    PinnedMessage {
        data: Box<Message>,
    },
    #[doc(hidden)]
    Unknown {
        raw: RawMessage
    }
}

impl Deserialize for Message {  // TODO(knsd): Remove .clone()
    fn deserialize<D>(deserializer: D) -> Result<Message, D::Error> where D: Deserializer {
        let raw: RawMessage = Deserialize::deserialize(deserializer)?;

        let id = raw.message_id;
        let from = raw.from.clone();
        let date = raw.date;
        let chat = raw.chat.clone();
        let reply_to_message = raw.reply_to_message.clone();
        let edit_date = raw.edit_date;
        let caption = raw.caption.clone();

        let forward = match (raw.forward_date, &raw.forward_from,
                             &raw.forward_from_chat, raw.forward_from_message_id) {
            (None, &None, &None, None) => None,
            (Some(date), &Some(ref from), &None, None) => {
                Some(Forward {
                    date: date,
                    from: ForwardFrom::User {
                        user: from.clone(),
                    },
                })
            },
            (Some(date), &None, &Some(Chat::Channel(ref channel)), Some(message_id)) => {
                Some(Forward {
                    date: date,
                    from: ForwardFrom::Channel {
                        channel: channel.clone(),
                        message_id: message_id,
                    },
                })
            },
            _ => {
                return Err(D::Error::custom("invalid forward fields combination"))
            }
        };

        let make_message = |kind| {
            Ok(Message {
                id: id,
                from: from,
                date: date,
                chat: chat,
                forward: forward,
                reply_to_message: reply_to_message,
                edit_date: edit_date,
                caption: caption,
                kind: kind,
            })
        };

        macro_rules! maybe_field {
            ($name:ident, $variant:ident) => {{
                if let Some(val) = raw.$name {
                    return make_message(MessageKind::$variant {
                        data: val
                    })
                }
            }}
        }

        macro_rules! maybe_true_field {
            ($name:ident, $variant:ident) => {{
                if let Some(True) = raw.$name {
                    return make_message(MessageKind::$variant)
                }
            }}
        }

        if let Some(text) = raw.text {
            let entities = raw.entities.unwrap_or_else(Vec::new);
            return make_message(MessageKind::Text {
                data: text,
                entities: entities,
            })
        }

        maybe_field!(audio, Audio);
        maybe_field!(document, Document);
        maybe_field!(photo, Photo);
        maybe_field!(sticker, Sticker);
        maybe_field!(video, Video);
        maybe_field!(voice, Voice);
        maybe_field!(contact, Contact);
        maybe_field!(location, Location);
        maybe_field!(venue, Venue);
        maybe_field!(new_chat_member, NewChatMember);
        maybe_field!(left_chat_member, LeftChatMember);
        maybe_field!(new_chat_title, NewChatTitle);
        maybe_field!(new_chat_photo, NewChatPhoto);
        maybe_true_field!(delete_chat_photo, DeleteChatPhoto);
        maybe_true_field!(delete_chat_photo, DeleteChatPhoto);
        maybe_true_field!(group_chat_created, GroupChatCreated);
        maybe_true_field!(supergroup_chat_created, SupergroupChatCreated);
        maybe_true_field!(channel_chat_created, ChannelChatCreated);
        maybe_field!(migrate_to_chat_id, MigrateToChatId);
        maybe_field!(migrate_from_chat_id, MigrateFromChatId);
        maybe_field!(pinned_message, PinnedMessage);

        make_message(MessageKind::Unknown {
            raw: raw,
        })
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct RawMessage {
    pub message_id: Integer,
    pub from: Option<User>,
    pub date: Integer,
    pub chat: Chat,
    pub forward_from: Option<User>,
    pub forward_from_chat: Option<Chat>,
    pub forward_from_message_id: Option<Integer>,
    pub forward_date: Option<Integer>,
    pub reply_to_message: Option<Box<Message>>,
    pub edit_date: Option<Integer>,
    pub text: Option<String>,
    pub entities: Option<Vec<MessageEntity>>,
    pub audio: Option<Audio>,
    pub document: Option<Document>,
//    pub game: Option<Game>,
    pub photo: Option<Vec<PhotoSize>>,
    pub sticker: Option<Sticker>,
    pub video: Option<Video>,
    pub voice: Option<Voice>,
    pub caption: Option<String>,
    pub contact: Option<Contact>,
    pub location: Option<Location>,
    pub venue: Option<Venue>,
    pub new_chat_member: Option<User>,
    pub left_chat_member: Option<User>,
    pub new_chat_title: Option<String>,
    pub new_chat_photo: Option<PhotoSize>,
    pub delete_chat_photo: Option<True>,
    pub group_chat_created: Option<True>,
    pub supergroup_chat_created: Option<True>,
    pub channel_chat_created: Option<True>,
    pub migrate_to_chat_id: Option<Integer>,
    pub migrate_from_chat_id: Option<Integer>,
    pub pinned_message: Option<Box<Message>>,
}

/// This object represents one special entity in a text message.
/// For example, hashtags, usernames, URLs, etc.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct MessageEntity {
    /// Offset in UTF-16 code units to the start of the entity
    offset: Integer,
    /// Length of the entity in UTF-16 code units
    length: Integer,
    /// Kind of the entity.
    kind: MessageEntityKind,
}

/// Kind of the entity.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum MessageEntityKind {
    Mention,
    Hashtag,
    BotCommand,
    Url,
    Email,
    Bold,
    Italic,
    Code,
    Pre,
    TextLink(String), // TODO(knsd) URL?
    TextMention(User),
    #[doc(hidden)]
    Unknown(RawMessageEntity),
}

impl Deserialize for MessageEntity {
    fn deserialize<D>(deserializer: D) -> Result<MessageEntity, D::Error> where D: Deserializer {
        use self::MessageEntityKind::*;

        let raw: RawMessageEntity = Deserialize::deserialize(deserializer)?;

        let offset = raw.offset;
        let length = raw.length;

        macro_rules! required_field {
            ($name:ident) => {{
                match raw.$name {
                    Some(val) => val,
                    None => return Err(D::Error::missing_field(stringify!($name)))
                }
            }}
        }

        let kind = match raw.type_.as_str() {
            "mention" => Mention,
            "hashtag" => Hashtag,
            "bot_command" => BotCommand,
            "url" => Url,
            "email" => Email,
            "bold" => Bold,
            "italic" => Italic,
            "code" => Code,
            "pre" => Pre,
            "text_link" => TextLink(required_field!(url)),
            "text_mention" => TextMention(required_field!(user)),
            _ => Unknown(raw),
        };

        Ok(MessageEntity {
            offset: offset,
            length: length,
            kind: kind,
        })
    }
}

/// This object represents one special entity in a text message.
/// For example, hashtags, usernames, URLs, etc. Directly mapped.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct RawMessageEntity {
    /// Type of the entity. Can be mention (@username), hashtag, bot_command, url, email,
    /// bold (bold text), italic (italic text), code (monowidth string), pre (monowidth block),
    /// text_link (for clickable text URLs), text_mention (for users without usernames).
    #[serde(rename="type")]
    pub type_: String,
    /// Offset in UTF-16 code units to the start of the entity.
    pub offset: Integer,
    /// Length of the entity in UTF-16 code units.
    pub length: Integer,
    /// For “text_link” only, url that will be opened after user taps on the text.
    pub url: Option<String>,
    /// For “text_mention” only, the mentioned user.
    pub user: Option<User>,
}

/// This object represents one size of a photo or a file / sticker thumbnail.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct PhotoSize {
    /// Unique identifier for this file.
    pub file_id: String,
    /// Photo width.
    pub width: Integer,
    /// Photo height.
    pub height: Integer,
    /// File size.
    pub file_size: Option<Integer>,
}

/// This object represents an audio file to be treated as music by the Telegram clients.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct Audio {
    /// Unique identifier for this file.
    pub file_id: String,
    /// Duration of the audio in seconds as defined by sender.
    pub duration: Integer,
    /// Performer of the audio as defined by sender or by audio tags.
    pub performer: Option<String>,
    /// Title of the audio as defined by sender or by audio tags.
    pub title: Option<String>,
    /// MIME type of the file as defined by sender.
    pub mime_type: Option<String>,
    /// File size.
    pub file_size: Option<Integer>,
}

/// This object represents a general file (as opposed to photos, voice messages and audio files).
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct Document {
    /// Unique file identifier.
    pub file_id: String,
    /// Document thumbnail as defined by sender.
    pub thumb: Option<PhotoSize>,
    /// Original filename as defined by sender.
    pub file_name: Option<String>,
    /// MIME type of the file as defined by sender.
    pub mime_type: Option<String>,
    /// File size.
    pub file_size: Option<Integer>,
}

/// This object represents a sticker.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct Sticker {
    /// Unique identifier for this file.
    pub file_id: String,
    /// Sticker width.
    pub width: Integer,
    /// Sticker height.
    pub height: Integer,
    /// Sticker thumbnail in .webp or .jpg format.
    pub thumb: Option<PhotoSize>,
    /// Emoji associated with the sticker.
    pub emoji: Option<String>,
    /// File size.
    pub file_size: Option<Integer>,
}

/// This object represents a video file.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct Video {
    /// Unique identifier for this file.
    pub file_id: String,
    /// Video width as defined by sender.
    pub width: Integer,
    /// Video height as defined by sender.
    pub height: Integer,
    /// Duration of the video in seconds as defined by sender.
    pub duration: Integer,
    /// Video thumbnail.
    pub thumb: Option<PhotoSize>,
    /// Mime type of a file as defined by sender.
    pub mime_type: Option<String>,
    /// File size.
    pub file_size: Option<Integer>,
}

/// This object represents a voice note.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct Voice {
    /// Unique identifier for this file.
    pub file_id: String,
    /// Duration of the audio in seconds as defined by sender.
    pub duration: Integer,
    /// MIME type of the file as defined by sender.
    pub mime_type: Option<String>,
    /// File size.
    pub file_size: Option<Integer>,
}

/// This object represents a phone contact.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct Contact {
    /// Contact's phone number.
    pub phone_number: String,
    /// Contact's first name.
    pub first_name: String,
    /// Contact's last name.
    pub last_name: Option<String>,
    /// Contact's user identifier in Telegram.
    pub user_id: Option<Integer>,
}

/// This object represents a point on the map.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct Location {
    /// Longitude as defined by sender.
    pub longitude: Float,
    /// Latitude as defined by sender.
    pub latitude: Float,
}

/// This object represents a venue.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct Venue {
    /// Venue location.
    pub location: Location,
    /// Name of the venue.
    pub title: String,
    /// Address of the venue.
    pub address: String,
    /// Foursquare identifier of the venue.
    pub foursquare_id: Option<String>,
}

/// This object represent a user's profile pictures.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct UserProfilePhotos {
    /// Total number of profile pictures the target user has.
    pub total_count: Integer,
    /// Requested profile pictures (in up to 4 sizes each).
    pub photos: Vec<Vec<PhotoSize>>,
}

/// This object represents a file ready to be downloaded.
/// The file can be downloaded via the link https://api.telegram.org/file/bot<token>/<file_path>.
/// It is guaranteed that the link will be valid for at least 1 hour.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct File {
    /// Unique identifier for this file.
    pub file_id: String,
    /// File size, if known.
    pub file_size: Option<Integer>,
    /// File path. Use https://api.telegram.org/file/bot<token>/<file_path> to get the file.
    pub file_path: Option<String>,
}
<|endoftext|>


<commit_before>extern crate libc;

use std::os::raw;
use std::ffi::CString;
use std::mem::{transmute, size_of};
use std::default::Default;

#[link(name = "kleeRuntest")]
extern {
    fn klee_make_symbolic(data: *const raw::c_void, length: libc::size_t, name: *const raw::c_char);
    fn klee_set_forking(state: bool);
}

pub unsafe fn any(data: *const raw::c_void, length: usize, name: &str) {
    klee_make_symbolic(data, length as libc::size_t, CString::new(name).unwrap().as_ptr());
}

pub fn set_forking(state: bool) {
    unsafe { klee_set_forking(state); }
}

pub fn some<T: Default>(name: &str) -> T {
    let new_symbol = T::default();
    symbol(&new_symbol, name);
    return new_symbol;
}

pub fn symbol<T>(data: *const T, name: &str) {
    unsafe{ any(transmute(data), size_of::<T>(), name); }
}
<commit_msg>Update lib.rs<commit_after>extern crate libc;

use std::os::raw;
use std::ffi::CString;
use std::mem::{transmute, size_of};
use std::default::Default;

#[link(name = "kleeRuntest")]
extern {
    fn klee_make_symbolic(data: *mut raw::c_void, length: libc::size_t, name: *const raw::c_char);
    fn klee_set_forking(state: bool);
}

pub unsafe fn any(data: *mut raw::c_void, length: usize, name: &str) {
    klee_make_symbolic(data, length as libc::size_t, CString::new(name).unwrap().as_ptr());
}

pub fn set_forking(state: bool) {
    unsafe { klee_set_forking(state); }
}

pub fn some<T: Default>(name: &str) -> T {
    let mut new_symbol = T::default();
    symbol(&new_symbol, name);
    return new_symbol;
}

pub fn symbol<T>(data: *mut T, name: &str) {
    unsafe{ any(transmute(data), size_of::<T>(), name); }
}
<|endoftext|>


<commit_before>pub mod topic;

pub fn parse_input(s: &str) -> Result<(&str, u8), &str> {
    let mut iter = s.split(",");
    (match (iter.next(), iter.next()) {
        (Some(topic), Some(n)) => Ok((topic, n)),
        _ => Err("Bad input")
    }).and_then(|(topic, n)| {
        n.trim()
            .parse::<u8>()
            .map(|num| { (topic, num) })
            .or(Err("Bad input"))
    })
}

#[test]
fn should_parse_valid_input() {

    let (topic, num) = parse_input("Dance, 42").unwrap();

    assert_eq!(num, 42);
    assert_eq!(topic, "Dance");
}

#[test]
fn should_fail_to_parse_non_number(){

    let result = parse_input("Comom, Lomom");

    assert_eq!(result, Err("Bad input"));
}

#[test]
fn should_fail_to_parse_missing_comma(){

    let result = parse_input("Toldom Acjdul");

    assert_eq!(result, Err("Bad input"));
}
<commit_msg>EM: refactoring parsing code<commit_after>pub mod topic;

pub fn parse_input(s: &str) -> Result<(&str, u8), &str> {
    let mut iter = s.split(",");
    match (iter.next(), iter.next()) {
        (Some(topic), Some(n)) => Ok((topic, n)),
        _ => Err("Bad input")
    }.and_then(|(topic, n)| {
        n.trim()
            .parse::<u8>()
            .map(|num| { (topic, num) })
            .or(Err("Bad input"))
    })
}

#[test]
fn should_parse_valid_input() {

    let (topic, num) = parse_input("Dance, 42").unwrap();

    assert_eq!(num, 42);
    assert_eq!(topic, "Dance");
}

#[test]
fn should_fail_to_parse_non_number(){

    let result = parse_input("Comom, Lomom");

    assert_eq!(result, Err("Bad input"));
}

#[test]
fn should_fail_to_parse_missing_comma(){

    let result = parse_input("Toldom Acjdul");

    assert_eq!(result, Err("Bad input"));
}
<|endoftext|>


<commit_before>#![feature(default_type_params)]
#![feature(macro_rules)]

#[deriving(Show)]
pub struct Oid(u32);

#[deriving(Show)]
pub struct TransactionId(u32);

#[deriving(Show)]
pub struct CommandId(u32);

pub type Datum = uint;

#[deriving(Show)]
pub struct BlockNumber(u32);

#[deriving(Show)]
pub struct BlockIdData {
    bi_hi: u16,
    bi_lo: u16,
}

#[deriving(Show)]
pub struct OffsetNumber(u16);

#[deriving(Show)]
pub struct ItemPointerData {
    ip_blkid: BlockIdData,
    ip_posid: OffsetNumber,
}

#[deriving(Show)]
#[repr(packed)]
pub struct HeapTupleFields {
    t_xmin: TransactionId, // inserting xact ID
    t_xmax: TransactionId, // deleting or locking xact ID
    t_cid: CommandId, // inserting or deleting command ID, or both
}

#[deriving(Show)]
pub struct NormalTupleHeaderData {
    t_heap: HeapTupleFields,
    t_ctid: ItemPointerData, // current t_ctid of this or newer tuple
}

#[deriving(Show)]
pub struct MinimalTupleHeaderData; // unit struct

bitflags! {
    #[deriving(Show)]
    flags HeapInfoMask: u16 {
        const HEAP_HASNULL  =           0x0001, // has null attribute(s)
        const HEAP_HASVARWIDTH =        0x0002, // has variable-width attribute(s)
        const HEAP_HASEXTERNAL =        0x0004, // has external stored attribute(s)
        const HEAP_HASOID =             0x0008, // has an object-id field
        const HEAP_XMAX_KEYSHR_LOCK =   0x0010, // xmax is a key-shared locker
        const HEAP_COMBOCID =           0x0020, // t_cid is a combo cid
        const HEAP_XMAX_EXCL_LOCK =     0x0040, // xmax is exclusive locker
        const HEAP_XMAX_LOCK_ONLY =     0x0080, // xmax, if valid, is only a locker

        // xmax is a shared locker
        const HEAP_XMAX_SHR_LOCK = HEAP_XMAX_EXCL_LOCK.bits | HEAP_XMAX_KEYSHR_LOCK.bits,
        const HEAP_LOCK_MASK = HEAP_XMAX_SHR_LOCK.bits | HEAP_XMAX_EXCL_LOCK.bits |
                               HEAP_XMAX_KEYSHR_LOCK.bits,

        const HEAP_XMIN_COMMITTED =   0x0100,  /* t_xmin committed */
        const HEAP_XMIN_INVALID =     0x0200,  /* t_xmin invalid/aborted */
        const HEAP_XMIN_FROZEN=      HEAP_XMIN_COMMITTED.bits|HEAP_XMIN_INVALID.bits,
        const HEAP_XMAX_COMMITTED =   0x0400,  /* t_xmax committed */
        const HEAP_XMAX_INVALID =     0x0800,  /* t_xmax invalid/aborted */
        const HEAP_XMAX_IS_MULTI =    0x1000,  /* t_xmax is a MultiXactId */
        const HEAP_UPDATED =          0x2000,  /* this is UPDATEd version of row */
        const HEAP_MOVED_OFF =        0x4000,  /* moved to another place by pre-9.0
                                               * VACUUM FULL; kept for binary
                                               * upgrade support */
        const HEAP_MOVED_IN =         0x8000,  /* moved from another place by pre-9.0
                                               * VACUUM FULL; kept for binary
                                               * upgrade support */
        const HEAP_MOVED = HEAP_MOVED_OFF.bits | HEAP_MOVED_IN.bits,
        const HEAP_XACT_MASK = 0xFFF0,  /* visibility-related bits */
    }
}

bitflags! {
    #[deriving(Show)]
    flags HeapInfoMask2: u16 {
        const HEAP_NATTS_MASK =     0x07FF, // 11 bits for number of attributes
        // bits 0x1800 are available
        const HEAP_KEYS_UPDATED =   0x2000, // tuple was updated and key cols modified, or tuple
                                            // deleted
        const HEAP_HOT_UPDATED =    0x4000, // tuple was HOT-updated
        const HEAP_ONLY_TUPLE =     0x8000, // this is heap-only tuple
        const HEAP2_XACT_MASK =     0xE000, // visibility-related bits

        /*
        * HEAP_TUPLE_HAS_MATCH is a temporary flag used during hash joins.  It is
        * only used in tuples that are in the hash table, and those don't need
        * any visibility information, so we can overlay it on a visibility flag
        * instead of using up a dedicated bit.
        */
        const HEAP_TUPLE_HAS_MATCH = HEAP_ONLY_TUPLE.bits,
    }
}

#[repr(C)]
pub struct HeapTupleHeaderData<T, Sized? D> {
    data_: T,
    // ^ - 18 bytes (normally) - ^
    t_infomask2: HeapInfoMask2, // number of attributes + various flags
    t_infomask: HeapInfoMask, // various flag bits, see below
    //t_hoff: u8, // sizeof header incl. bitmap, padding
    // ^ - 5 bytes, 23 bytes total (normally) - ^
    //bits_: [u8, .. 0], // bitmap of NULLs -- VARIABLE LENGTH
    rest_: D, // More bits (if necessary) plus user data (suitably aligned)
}

impl<T, Sized? D> Deref<T> for HeapTupleHeaderData<T, D> {
    #[inline]
    fn deref(&self) -> &T { &self.data_ }
}

/*impl<T> DerefMut<T> for HeapTupleHeaderData<T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T { &mut self.t_data_ }
}*/

#[repr(C)]
pub struct HeapTupleHeader<T, Sized? U> {
    t_len: u32, // length of *t_data
    header_: T,
    t_data: U, // -> tuple header and data
}

pub struct HeapTupleTemp;

pub struct HeapTupleDisk {
    t_self: ItemPointerData, // SelfItemPointer
    t_table_oid: Oid, // table the tuple came from
}

impl<T, U> Deref<T> for HeapTupleHeader<T, U> {
    fn deref(&self) -> &T {
        &self.header_
    }
}

impl<T, U> DerefMut<T> for HeapTupleHeader<T, U> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.header_
    }
}

pub type HeapTupleIndirectData<'a, T, U = NormalTupleHeaderData, D = [Datum]> = HeapTupleHeader<T, &'a HeapTupleHeaderData<U, D>>;

pub type HeapTupleContiguousData<T, U = NormalTupleHeaderData, D = [Datum]> = HeapTupleHeader<T, HeapTupleHeaderData<U, D>>;

pub const MAXIMUM_ALIGNOF: uint = 8;

macro_rules! with_offset(($ty:ty,$field:ident,$data:ident,$b:expr) => {
    unsafe {
        let $data = 0 as *const $ty;
        let $field = &(*$data).$field;
        let result = $b;
        result
    }
})

macro_rules! offset_of(($ty:ty,$field:ident) => {
    with_offset!($ty, $field, data, ($field as *const _ as uint) - (data as uint))
})

macro_rules! min_align_of_offset(($ty:ty,$field:ident) => {
    with_offset!($ty, $field, data, ::std::mem::min_align_of_val($field))
})

// (offsetof(HeapTupleHeaderData, t_infomask2) - sizeof(uint32)) % MAXIMUM_ALIGNOF
pub const MINIMAL_TUPLE_PADDING: uint = 6;

/*pub struct Version {
    version: uint,
}

pub struct Transaction {
    version: Version,
}

pub const BUFFER_SIZE: uint = 512;

struct Buffer {
    buffer: Arc<RwLock<[u8, .. BUFFER_SIZE]>>,
}

struct Page {
    : UnsafeCell<T>,
}

struct Database {
    pages: Pages,
}

pub struct TransactionManager {
    transactions: *T,
    database: Database,
}*/

#[cfg(test)]
mod tests {
    use std::mem;
    use std::u32;
    use super::{
        Datum,
        HeapTupleContiguousData,
        HeapTupleIndirectData,
        HeapTupleDisk,
        HeapTupleHeaderData,
        HeapTupleTemp,
        HeapInfoMask,
        HeapInfoMask2,
        MinimalTupleHeaderData,
        NormalTupleHeaderData,
    };

    #[test]
    fn maximum_alignof() {
        assert_eq!(mem::align_of::<uint>(), super::MAXIMUM_ALIGNOF);
    }

    #[test]
    fn heap_form_tuple() {
        let tuple: &HeapTupleHeaderData<MinimalTupleHeaderData, [Datum]> = &HeapTupleHeaderData {
            data_: MinimalTupleHeaderData,
            // ^ - 18 bytes (normally) - ^
            t_infomask2: HeapInfoMask2::empty(),
            t_infomask: super::HEAP_LOCK_MASK,
            //t_hoff: 0,
            //bits_: [],
            rest_: [1],
        };
        println!("{}: {}", &tuple.rest_, tuple.t_infomask);
        //assert_eq!(mem::align_of_val(&tuple.rest_), super::MAXIMUM_ALIGNOF);
    }

    #[test]
    // (offsetof(HeapTupleHeaderData, t_infomask2) - sizeof(uint32)) % MAXIMUM_ALIGNOF
    fn minimal_tuple_padding() {
        type C<T, U, D> = HeapTupleContiguousData<T, U, D>;
        type I<'a, T, U, D> = HeapTupleIndirectData<'a, T, U, D>;
        type T = HeapTupleTemp;
        type S = HeapTupleDisk;
        type M = MinimalTupleHeaderData;
        type N = NormalTupleHeaderData;
        type D = [Datum, .. 0];
        let offset = offset_of!(HeapTupleHeaderData<M, D>, rest_);
        let align = min_align_of_offset!(HeapTupleHeaderData<M, D>, rest_);
        println!("{} {} {}", offset, mem::size_of::<HeapTupleHeaderData<M, D>>(), align);
        assert_eq!(align, super::MAXIMUM_ALIGNOF);
        let offset = offset_of!(HeapTupleHeaderData<N, D>, rest_);
        let align = min_align_of_offset!(HeapTupleHeaderData<N, D>, rest_);
        println!("{} {} {}", offset, mem::size_of::<HeapTupleHeaderData<N, D>>(), align);
        assert_eq!(align, super::MAXIMUM_ALIGNOF);

        let offset = offset_of!(C<T, M, D>, t_data);
        println!("{} {}", offset, mem::size_of::<C<T, M, D>>());
        let offset = offset_of!(I<T, N, D>, t_data);
        println!("{} {}", offset, mem::size_of::<I<T, N, D>>());
        let offset = offset_of!(I<S, N, D>, t_data);
        println!("{} {}", offset, mem::size_of::<I<S, N, D>>());
        let offset = offset_of!(C<S, M, D>, t_data);
        println!("{} {}", offset, mem::size_of::<C<S, M, D>>());
        let offset = offset_of!(C<T, N, D>, t_data);
        println!("{} {}", offset, mem::size_of::<C<T, N, D>>());
        let offset = offset_of!(C<S, N, D>, t_data);
        println!("{} {}", offset, mem::size_of::<C<S, N, D>>());

        let offset = offset_of!(HeapTupleHeaderData<N, D>, t_infomask2);
        //println!("{} {}", offset, mem::size_of::<HeapTupleHeaderData<N, D>>());
        let minimal_tuple_padding = (offset - u32::BYTES) % super::MAXIMUM_ALIGNOF;
        assert_eq!(minimal_tuple_padding, super::MINIMAL_TUPLE_PADDING);
    }
}
<commit_msg>Commenting out flags we aren't using.<commit_after>#![feature(default_type_params)]
#![feature(macro_rules)]

#[deriving(Show)]
pub struct Oid(u32);

#[deriving(Show)]
pub struct TransactionId(u32);

#[deriving(Show)]
pub struct CommandId(u32);

pub type Datum = uint;

#[deriving(Show)]
pub struct BlockNumber(u32);

#[deriving(Show)]
pub struct BlockIdData {
    bi_hi: u16,
    bi_lo: u16,
}

#[deriving(Show)]
pub struct OffsetNumber(u16);

#[deriving(Show)]
pub struct ItemPointerData {
    ip_blkid: BlockIdData,
    ip_posid: OffsetNumber,
}

#[deriving(Show)]
#[repr(packed)]
pub struct HeapTupleFields {
    t_xmin: TransactionId, // inserting xact ID
    t_xmax: TransactionId, // deleting or locking xact ID
    t_cid: CommandId, // inserting or deleting command ID, or both
}

#[deriving(Show)]
pub struct NormalTupleHeaderData {
    t_heap: HeapTupleFields,
    t_ctid: ItemPointerData, // current t_ctid of this or newer tuple
}

#[deriving(Show)]
pub struct MinimalTupleHeaderData; // unit struct

bitflags! {
    #[deriving(Show)]
    flags HeapInfoMask: u16 {
        //const HEAP_HASNULL  =           0x0001, // has null attribute(s)
        //const HEAP_HASVARWIDTH =        0x0002, // has variable-width attribute(s)
        //const HEAP_HASEXTERNAL =        0x0004, // has external stored attribute(s)
        //const HEAP_HASOID =             0x0008, // has an object-id field
        const HEAP_XMAX_KEYSHR_LOCK =   0x0010, // xmax is a key-shared locker
        const HEAP_COMBOCID =           0x0020, // t_cid is a combo cid
        const HEAP_XMAX_EXCL_LOCK =     0x0040, // xmax is exclusive locker
        const HEAP_XMAX_LOCK_ONLY =     0x0080, // xmax, if valid, is only a locker

        // xmax is a shared locker
        const HEAP_XMAX_SHR_LOCK = HEAP_XMAX_EXCL_LOCK.bits | HEAP_XMAX_KEYSHR_LOCK.bits,
        const HEAP_LOCK_MASK = HEAP_XMAX_SHR_LOCK.bits | HEAP_XMAX_EXCL_LOCK.bits |
                               HEAP_XMAX_KEYSHR_LOCK.bits,

        const HEAP_XMIN_COMMITTED =   0x0100,  /* t_xmin committed */
        const HEAP_XMIN_INVALID =     0x0200,  /* t_xmin invalid/aborted */
        const HEAP_XMIN_FROZEN=      HEAP_XMIN_COMMITTED.bits|HEAP_XMIN_INVALID.bits,
        const HEAP_XMAX_COMMITTED =   0x0400,  /* t_xmax committed */
        const HEAP_XMAX_INVALID =     0x0800,  /* t_xmax invalid/aborted */
        const HEAP_XMAX_IS_MULTI =    0x1000,  /* t_xmax is a MultiXactId */
        const HEAP_UPDATED =          0x2000,  /* this is UPDATEd version of row */
        /*const HEAP_MOVED_OFF =        0x4000,  /* moved to another place by pre-9.0
                                               * VACUUM FULL; kept for binary
                                               * upgrade support */
        const HEAP_MOVED_IN =         0x8000,  /* moved from another place by pre-9.0
                                               * VACUUM FULL; kept for binary
                                               * upgrade support */
        const HEAP_MOVED = HEAP_MOVED_OFF.bits | HEAP_MOVED_IN.bits,*/
        const HEAP_XACT_MASK = 0xFFF0,  /* visibility-related bits */
    }
}

bitflags! {
    #[deriving(Show)]
    flags HeapInfoMask2: u16 {
        const HEAP_NATTS_MASK =     0x07FF, // 11 bits for number of attributes
        // bits 0x1800 are available
        //const HEAP_KEYS_UPDATED =   0x2000, // tuple was updated and key cols modified, or tuple
        //                                    // deleted
        //const HEAP_HOT_UPDATED =    0x4000, // tuple was HOT-updated
        //const HEAP_ONLY_TUPLE =     0x8000, // this is heap-only tuple
        const HEAP2_XACT_MASK =     0xE000, // visibility-related bits

        /*
        * HEAP_TUPLE_HAS_MATCH is a temporary flag used during hash joins.  It is
        * only used in tuples that are in the hash table, and those don't need
        * any visibility information, so we can overlay it on a visibility flag
        * instead of using up a dedicated bit.
        */
        //const HEAP_TUPLE_HAS_MATCH = HEAP_ONLY_TUPLE.bits,
    }
}

#[repr(C)]
pub struct HeapTupleHeaderData<T, Sized? D> {
    data_: T,
    // ^ - 18 bytes (normally) - ^
    t_infomask2: HeapInfoMask2, // number of attributes + various flags
    t_infomask: HeapInfoMask, // various flag bits, see below
    //t_hoff: u8, // sizeof header incl. bitmap, padding
    // ^ - 5 bytes, 23 bytes total (normally) - ^
    //bits_: [u8, .. 0], // bitmap of NULLs -- VARIABLE LENGTH
    rest_: D, // More bits (if necessary) plus user data (suitably aligned)
}

impl<T, Sized? D> Deref<T> for HeapTupleHeaderData<T, D> {
    #[inline]
    fn deref(&self) -> &T { &self.data_ }
}

/*impl<T> DerefMut<T> for HeapTupleHeaderData<T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T { &mut self.t_data_ }
}*/

#[repr(C)]
pub struct HeapTupleHeader<T, Sized? U> {
    t_len: u32, // length of *t_data
    header_: T,
    t_data: U, // -> tuple header and data
}

pub struct HeapTupleTemp;

pub struct HeapTupleDisk {
    t_self: ItemPointerData, // SelfItemPointer
    t_table_oid: Oid, // table the tuple came from
}

impl<T, U> Deref<T> for HeapTupleHeader<T, U> {
    fn deref(&self) -> &T {
        &self.header_
    }
}

impl<T, U> DerefMut<T> for HeapTupleHeader<T, U> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.header_
    }
}

pub type HeapTupleIndirectData<'a, T, U = NormalTupleHeaderData, D = [Datum]> = HeapTupleHeader<T, &'a HeapTupleHeaderData<U, D>>;

pub type HeapTupleContiguousData<T, U = NormalTupleHeaderData, D = [Datum]> = HeapTupleHeader<T, HeapTupleHeaderData<U, D>>;

pub const MAXIMUM_ALIGNOF: uint = 8;

macro_rules! with_offset(($ty:ty,$field:ident,$data:ident,$b:expr) => {
    unsafe {
        let $data = 0 as *const $ty;
        let $field = &(*$data).$field;
        let result = $b;
        result
    }
})

macro_rules! offset_of(($ty:ty,$field:ident) => {
    with_offset!($ty, $field, data, ($field as *const _ as uint) - (data as uint))
})

macro_rules! min_align_of_offset(($ty:ty,$field:ident) => {
    with_offset!($ty, $field, data, ::std::mem::min_align_of_val($field))
})

// (offsetof(HeapTupleHeaderData, t_infomask2) - sizeof(uint32)) % MAXIMUM_ALIGNOF
pub const MINIMAL_TUPLE_PADDING: uint = 6;

/*pub struct Version {
    version: uint,
}

pub struct Transaction {
    version: Version,
}

pub const BUFFER_SIZE: uint = 512;

struct Buffer {
    buffer: Arc<RwLock<[u8, .. BUFFER_SIZE]>>,
}

struct Page {
    : UnsafeCell<T>,
}

struct Database {
    pages: Pages,
}

pub struct TransactionManager {
    transactions: *T,
    database: Database,
}*/

#[cfg(test)]
mod tests {
    use std::mem;
    use std::u32;
    use super::{
        Datum,
        HeapTupleContiguousData,
        HeapTupleIndirectData,
        HeapTupleDisk,
        HeapTupleHeaderData,
        HeapTupleTemp,
        HeapInfoMask2,
        MinimalTupleHeaderData,
        NormalTupleHeaderData,
    };

    #[test]
    fn maximum_alignof() {
        assert_eq!(mem::align_of::<uint>(), super::MAXIMUM_ALIGNOF);
    }

    #[test]
    fn heap_form_tuple() {
        let tuple: &HeapTupleHeaderData<MinimalTupleHeaderData, [Datum]> = &HeapTupleHeaderData {
            data_: MinimalTupleHeaderData,
            // ^ - 18 bytes (normally) - ^
            t_infomask2: HeapInfoMask2::empty(),
            t_infomask: super::HEAP_LOCK_MASK,
            //t_hoff: 0,
            //bits_: [],
            rest_: [1],
        };
        println!("{}: {}", &tuple.rest_, tuple.t_infomask);
        //assert_eq!(mem::align_of_val(&tuple.rest_), super::MAXIMUM_ALIGNOF);
    }

    #[test]
    // (offsetof(HeapTupleHeaderData, t_infomask2) - sizeof(uint32)) % MAXIMUM_ALIGNOF
    fn minimal_tuple_padding() {
        type C<T, U, D> = HeapTupleContiguousData<T, U, D>;
        type I<'a, T, U, D> = HeapTupleIndirectData<'a, T, U, D>;
        type T = HeapTupleTemp;
        type S = HeapTupleDisk;
        type M = MinimalTupleHeaderData;
        type N = NormalTupleHeaderData;
        type D = [Datum, .. 0];
        let offset = offset_of!(HeapTupleHeaderData<M, D>, rest_);
        let align = min_align_of_offset!(HeapTupleHeaderData<M, D>, rest_);
        println!("{} {} {}", offset, mem::size_of::<HeapTupleHeaderData<M, D>>(), align);
        assert_eq!(align, super::MAXIMUM_ALIGNOF);
        let offset = offset_of!(HeapTupleHeaderData<N, D>, rest_);
        let align = min_align_of_offset!(HeapTupleHeaderData<N, D>, rest_);
        println!("{} {} {}", offset, mem::size_of::<HeapTupleHeaderData<N, D>>(), align);
        assert_eq!(align, super::MAXIMUM_ALIGNOF);

        let offset = offset_of!(C<T, M, D>, t_data);
        println!("{} {}", offset, mem::size_of::<C<T, M, D>>());
        let offset = offset_of!(I<T, N, D>, t_data);
        println!("{} {}", offset, mem::size_of::<I<T, N, D>>());
        let offset = offset_of!(I<S, N, D>, t_data);
        println!("{} {}", offset, mem::size_of::<I<S, N, D>>());
        let offset = offset_of!(C<S, M, D>, t_data);
        println!("{} {}", offset, mem::size_of::<C<S, M, D>>());
        let offset = offset_of!(C<T, N, D>, t_data);
        println!("{} {}", offset, mem::size_of::<C<T, N, D>>());
        let offset = offset_of!(C<S, N, D>, t_data);
        println!("{} {}", offset, mem::size_of::<C<S, N, D>>());

        let offset = offset_of!(HeapTupleHeaderData<N, D>, t_infomask2);
        //println!("{} {}", offset, mem::size_of::<HeapTupleHeaderData<N, D>>());
        let minimal_tuple_padding = (offset - u32::BYTES) % super::MAXIMUM_ALIGNOF;
        assert_eq!(minimal_tuple_padding, super::MINIMAL_TUPLE_PADDING);
    }
}
<|endoftext|>


<commit_before>#![no_std]

#[doc(hidden)]
pub extern crate core as _core;

/// Asserts at compile-time that the two types have equal sizes.
#[macro_export]
macro_rules! assert_eq_size {
    ($x:ty, $y:ty) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::mem::{forget, transmute, uninitialized};
            forget::<$y>(transmute(uninitialized::<$x>()));
        }
    };
    ($x:ty, $y:ty, $($rest:ty),+) => {
        assert_eq_size!($x, $y);
        assert_eq_size!($y, $($rest),+);
    };
}
<commit_msg>Add example to assert_eq_size doc<commit_after>#![no_std]

#[doc(hidden)]
pub extern crate core as _core;

/// Asserts at compile-time that the two types have equal sizes.
///
/// # Example
///
/// ```
/// #[macro_use]
/// extern crate static_assertions;
///
/// struct Byte(u8);
///
/// fn main() {
///     assert_eq_size!(Byte, u8);
///     // assert_eq_size!(Byte, u16); // Fails to compile
///
///     // Supports unlimited arguments:
///     assert_eq_size!([Byte; 4], [u16; 2], u32);
/// }
/// ```
#[macro_export]
macro_rules! assert_eq_size {
    ($x:ty, $y:ty) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::mem::{forget, transmute, uninitialized};
            forget::<$y>(transmute(uninitialized::<$x>()));
        }
    };
    ($x:ty, $y:ty, $($rest:ty),+) => {
        assert_eq_size!($x, $y);
        assert_eq_size!($y, $($rest),+);
    };
}
<|endoftext|>