<commit_before>extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate rmp;
extern crate rmp_serde as rmps;

use std::borrow::Cow;
use std::io::Cursor;

use serde::{Deserialize, Serialize};
use rmps::{Deserializer, Serializer};

#[test]
fn round_trip_option() {
    #[derive(Debug, PartialEq, Serialize, Deserialize)]
    struct Foo {
        v: Option<Vec<u8>>,
    }

    let expected = Foo { v: None };

    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(Cursor::new(&buf[..]));

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_trip_optional_enum() {
    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    pub enum SimpleEnum {
        Variant,
    }
    let expected = Some(SimpleEnum::Variant);

    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(Cursor::new(&buf[..]));
    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_trip_cow() {
    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    struct Foo<'a> {
        v: Cow<'a, [u8]>,
    }

    let expected = Foo { v : Cow::Borrowed(&[]) };

    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(Cursor::new(&buf[..]));

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_trip_option_cow() {
    use std::borrow::Cow;
    use std::io::Cursor;
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    struct Foo<'a> {
        v: Option<Cow<'a, [u8]>>,
    }

    let expected = Foo { v : None };

    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(Cursor::new(&buf[..]));

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_struct_like_enum() {
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Enum {
        A { data: u32 },
    }

    let expected = Enum::A { data: 42 };
    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(&buf[..]);

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_struct_like_enum_with_struct_map() {
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Enum {
        A { data: u32 },
    }

    let expected = Enum::A { data: 42 };
    let mut buf = Vec::new();
    expected
        .serialize(&mut Serializer::new(&mut buf).with_struct_map())
        .unwrap();

    let mut de = Deserializer::new(&buf[..]);

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_struct_like_enum_with_struct_tuple() {
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Enum {
        A { data: u32 },
    }

    let expected = Enum::A { data: 42 };
    let mut buf = Vec::new();
    expected
        .serialize(&mut Serializer::new(&mut buf).with_struct_tuple())
        .unwrap();

    let mut de = Deserializer::new(&buf[..]);

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_enum_with_newtype_struct() {
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    struct Newtype(String);

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Enum {
        A(Newtype),
    }

    let expected = Enum::A(Newtype("le message".into()));
    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(&buf[..]);

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_trip_untagged_enum_with_enum_associated_data() {
    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    #[serde(untagged)]
    enum Foo {
        A(Bar),
    }

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Bar {
        B,
        C(String),
        D(u64, u64, u64),
        E{f1: String},
    }

    let data1_1 = Foo::A(Bar::B);
    let bytes_1 = rmps::to_vec(&data1_1).unwrap();
    let data1_2 = rmps::from_slice(&bytes_1).unwrap();
    assert_eq!(data1_1, data1_2);

    let data2_1 = Foo::A(Bar::C("Hello".into()));
    let bytes_2 = rmps::to_vec(&data2_1).unwrap();
    let data2_2 = rmps::from_slice(&bytes_2).unwrap();
    assert_eq!(data2_1, data2_2);

    let data3_1 = Foo::A(Bar::D(1,2,3));
    let bytes_3 = rmps::to_vec(&data3_1).unwrap();
    let data3_2 = rmps::from_slice(&bytes_3).unwrap();
    assert_eq!(data3_1, data3_2);

    let data4_1 = Foo::A(Bar::E{f1: "Hello".into()});
    let bytes_4 = rmps::to_vec(&data4_1).unwrap();
    let data4_2 = rmps::from_slice(&bytes_4).unwrap();
    assert_eq!(data4_1, data4_2);
}

// Checks whether deserialization and serialization can both work with structs as maps
#[test]
fn round_struct_as_map() {
    use rmps::to_vec_named;
    use rmps::decode::from_slice;

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Dog1 {
        name: String,
        age: u16,
    }
    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Dog2 {
        age: u16,
        name: String,
    }

    let dog1 = Dog1 {
        name: "Frankie".into(),
        age: 42,
    };

    let serialized: Vec<u8> = to_vec_named(&dog1).unwrap();
    let deserialized: Dog2 = from_slice(&serialized).unwrap();

    let check = Dog1 {
        age: deserialized.age,
        name: deserialized.name,
    };

    assert_eq!(dog1, check);
}

#[test]
fn round_trip_unit_struct() {
    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Message1 {
        data: u8,
    }

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Message2;

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    enum Messages {
        Message1(Message1),
        Message2(Message2),
    }

    let msg2 = Messages::Message2(Message2);

    // struct-as-tuple
    {
        let serialized: Vec<u8> = rmps::to_vec(&msg2).unwrap();
        let deserialized: Messages = rmps::from_slice(&serialized).unwrap();
        assert_eq!(deserialized, msg2);
    }

    // struct-as-map
    {
        let serialized: Vec<u8> = rmps::to_vec_named(&msg2).unwrap();
        let deserialized: Messages = rmps::from_slice(&serialized).unwrap();
        assert_eq!(deserialized, msg2);
    }
}

#[test]
#[ignore]
fn round_trip_unit_struct_untagged_enum() {
    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct UnitStruct;

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct MessageA {
        some_int: i32,
        unit: UnitStruct,
    }

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    #[serde(untagged)]
    enum Messages {
        MessageA(MessageA),
    }

    let msga = Messages::MessageA(MessageA {
        some_int: 32,
        unit: UnitStruct,
    });

    // struct-as-tuple
    {
        let serialized: Vec<u8> = rmps::to_vec(&msga).unwrap();
        let deserialized: Messages = rmps::from_slice(&serialized).unwrap();
        assert_eq!(deserialized, msga);
    }

    // struct-as-map
    {
        let serialized: Vec<u8> = rmps::to_vec_named(&msga).unwrap();
        let deserialized: Messages = rmps::from_slice(&serialized).unwrap();
        assert_eq!(deserialized, msga);
    }
}
<commit_msg>Add test for configuration persisting in structs nested in lists<commit_after>extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate rmp;
extern crate rmp_serde as rmps;

use std::borrow::Cow;
use std::io::Cursor;

use serde::{Deserialize, Serialize};
use rmps::{Deserializer, Serializer};

#[test]
fn round_trip_option() {
    #[derive(Debug, PartialEq, Serialize, Deserialize)]
    struct Foo {
        v: Option<Vec<u8>>,
    }

    let expected = Foo { v: None };

    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(Cursor::new(&buf[..]));

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_trip_optional_enum() {
    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    pub enum SimpleEnum {
        Variant,
    }
    let expected = Some(SimpleEnum::Variant);

    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(Cursor::new(&buf[..]));
    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_trip_cow() {
    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    struct Foo<'a> {
        v: Cow<'a, [u8]>,
    }

    let expected = Foo { v : Cow::Borrowed(&[]) };

    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(Cursor::new(&buf[..]));

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_trip_option_cow() {
    use std::borrow::Cow;
    use std::io::Cursor;
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    struct Foo<'a> {
        v: Option<Cow<'a, [u8]>>,
    }

    let expected = Foo { v : None };

    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(Cursor::new(&buf[..]));

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_struct_like_enum() {
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Enum {
        A { data: u32 },
    }

    let expected = Enum::A { data: 42 };
    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(&buf[..]);

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_struct_like_enum_with_struct_map() {
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Enum {
        A { data: u32 },
    }

    let expected = Enum::A { data: 42 };
    let mut buf = Vec::new();
    expected
        .serialize(&mut Serializer::new(&mut buf).with_struct_map())
        .unwrap();

    let mut de = Deserializer::new(&buf[..]);

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_struct_like_enum_with_struct_tuple() {
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Enum {
        A { data: u32 },
    }

    let expected = Enum::A { data: 42 };
    let mut buf = Vec::new();
    expected
        .serialize(&mut Serializer::new(&mut buf).with_struct_tuple())
        .unwrap();

    let mut de = Deserializer::new(&buf[..]);

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_enum_with_newtype_struct() {
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    struct Newtype(String);

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Enum {
        A(Newtype),
    }

    let expected = Enum::A(Newtype("le message".into()));
    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(&buf[..]);

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_trip_untagged_enum_with_enum_associated_data() {
    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    #[serde(untagged)]
    enum Foo {
        A(Bar),
    }

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Bar {
        B,
        C(String),
        D(u64, u64, u64),
        E{f1: String},
    }

    let data1_1 = Foo::A(Bar::B);
    let bytes_1 = rmps::to_vec(&data1_1).unwrap();
    let data1_2 = rmps::from_slice(&bytes_1).unwrap();
    assert_eq!(data1_1, data1_2);

    let data2_1 = Foo::A(Bar::C("Hello".into()));
    let bytes_2 = rmps::to_vec(&data2_1).unwrap();
    let data2_2 = rmps::from_slice(&bytes_2).unwrap();
    assert_eq!(data2_1, data2_2);

    let data3_1 = Foo::A(Bar::D(1,2,3));
    let bytes_3 = rmps::to_vec(&data3_1).unwrap();
    let data3_2 = rmps::from_slice(&bytes_3).unwrap();
    assert_eq!(data3_1, data3_2);

    let data4_1 = Foo::A(Bar::E{f1: "Hello".into()});
    let bytes_4 = rmps::to_vec(&data4_1).unwrap();
    let data4_2 = rmps::from_slice(&bytes_4).unwrap();
    assert_eq!(data4_1, data4_2);
}

// Checks whether deserialization and serialization can both work with structs as maps
#[test]
fn round_struct_as_map() {
    use rmps::to_vec_named;
    use rmps::decode::from_slice;

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Dog1 {
        name: String,
        age: u16,
    }
    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Dog2 {
        age: u16,
        name: String,
    }

    let dog1 = Dog1 {
        name: "Frankie".into(),
        age: 42,
    };

    let serialized: Vec<u8> = to_vec_named(&dog1).unwrap();
    let deserialized: Dog2 = from_slice(&serialized).unwrap();

    let check = Dog1 {
        age: deserialized.age,
        name: deserialized.name,
    };

    assert_eq!(dog1, check);
}

#[test]
fn round_struct_as_map_in_vec() {
    // See: issue #205
    use rmps::decode::from_slice;
    use rmps::to_vec_named;

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Dog1 {
        name: String,
        age: u16,
    }
    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Dog2 {
        age: u16,
        name: String,
    }

    let dog1 = Dog1 {
        name: "Frankie".into(),
        age: 42,
    };

    let data = vec![dog1];

    let serialized: Vec<u8> = to_vec_named(&data).unwrap();
    let deserialized: Vec<Dog2> = from_slice(&serialized).unwrap();

    let dog2 = &deserialized[0];

    assert_eq!(dog2.name, "Frankie");
    assert_eq!(dog2.age, 42);
}

#[test]
fn round_trip_unit_struct() {
    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Message1 {
        data: u8,
    }

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Message2;

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    enum Messages {
        Message1(Message1),
        Message2(Message2),
    }

    let msg2 = Messages::Message2(Message2);

    // struct-as-tuple
    {
        let serialized: Vec<u8> = rmps::to_vec(&msg2).unwrap();
        let deserialized: Messages = rmps::from_slice(&serialized).unwrap();
        assert_eq!(deserialized, msg2);
    }

    // struct-as-map
    {
        let serialized: Vec<u8> = rmps::to_vec_named(&msg2).unwrap();
        let deserialized: Messages = rmps::from_slice(&serialized).unwrap();
        assert_eq!(deserialized, msg2);
    }
}

#[test]
#[ignore]
fn round_trip_unit_struct_untagged_enum() {
    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct UnitStruct;

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct MessageA {
        some_int: i32,
        unit: UnitStruct,
    }

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    #[serde(untagged)]
    enum Messages {
        MessageA(MessageA),
    }

    let msga = Messages::MessageA(MessageA {
        some_int: 32,
        unit: UnitStruct,
    });

    // struct-as-tuple
    {
        let serialized: Vec<u8> = rmps::to_vec(&msga).unwrap();
        let deserialized: Messages = rmps::from_slice(&serialized).unwrap();
        assert_eq!(deserialized, msga);
    }

    // struct-as-map
    {
        let serialized: Vec<u8> = rmps::to_vec_named(&msga).unwrap();
        let deserialized: Messages = rmps::from_slice(&serialized).unwrap();
        assert_eq!(deserialized, msga);
    }
}
<|endoftext|>


<commit_before>//! We setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself during the
//! initial `cargo check`. That way, we avoid checking the actual project, and
//! only build proc macros and build.rs.
//!
//! Code taken from IntelliJ :0)
//!     https://github.com/intellij-rust/intellij-rust/blob/master/native-helper/src/main.rs
use std::{
    ffi::OsString,
    io,
    process::{Command, Stdio},
};

/// ExitCode/ExitStatus are impossible to create :(.
pub(crate) struct ExitCode(pub(crate) Option<i32>);

pub(crate) fn run_rustc_skipping_cargo_checking(
    rustc_executable: OsString,
    args: Vec<OsString>,
) -> io::Result<ExitCode> {
    let is_cargo_check = args.iter().any(|arg| {
        let arg = arg.to_string_lossy();
        // `cargo check` invokes `rustc` with `--emit=metadata` argument.
        //
        // https://doc.rust-lang.org/rustc/command-line-arguments.html#--emit-specifies-the-types-of-output-files-to-generate
        // link —     Generates the crates specified by --crate-type. The default
        //            output filenames depend on the crate type and platform. This
        //            is the default if --emit is not specified.
        // metadata — Generates a file containing metadata about the crate.
        //            The default output filename is CRATE_NAME.rmeta.
        arg.starts_with("--emit=") && arg.contains("metadata") && !arg.contains("link")
    });
    if is_cargo_check {
        return Ok(ExitCode(Some(0)));
    }
    run_rustc(rustc_executable, args)
}

fn run_rustc(rustc_executable: OsString, args: Vec<OsString>) -> io::Result<ExitCode> {
    let mut child = Command::new(rustc_executable)
        .args(args)
        .stdin(Stdio::inherit())
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .spawn()?;
    Ok(ExitCode(child.wait()?.code()))
}
<commit_msg>Do not unconditionally succeed RUSTC_WRAPPER checks when run by build scripts<commit_after>//! We setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself during the
//! initial `cargo check`. That way, we avoid checking the actual project, and
//! only build proc macros and build.rs.
//!
//! Code taken from IntelliJ :0)
//!     https://github.com/intellij-rust/intellij-rust/blob/master/native-helper/src/main.rs
use std::{
    ffi::OsString,
    io,
    process::{Command, Stdio},
};

/// ExitCode/ExitStatus are impossible to create :(.
pub(crate) struct ExitCode(pub(crate) Option<i32>);

pub(crate) fn run_rustc_skipping_cargo_checking(
    rustc_executable: OsString,
    args: Vec<OsString>,
) -> io::Result<ExitCode> {
    // `CARGO_CFG_TARGET_ARCH` is only set by cargo when executing build scripts
    // We don't want to exit out checks unconditionally with success if a build
    // script tries to invoke checks themselves
    // See https://github.com/rust-lang/rust-analyzer/issues/12973 for context
    let not_invoked_by_build_script = std::env::var_os("CARGO_CFG_TARGET_ARCH").is_none();
    let is_cargo_check = args.iter().any(|arg| {
        let arg = arg.to_string_lossy();
        // `cargo check` invokes `rustc` with `--emit=metadata` argument.
        //
        // https://doc.rust-lang.org/rustc/command-line-arguments.html#--emit-specifies-the-types-of-output-files-to-generate
        // link —     Generates the crates specified by --crate-type. The default
        //            output filenames depend on the crate type and platform. This
        //            is the default if --emit is not specified.
        // metadata — Generates a file containing metadata about the crate.
        //            The default output filename is CRATE_NAME.rmeta.
        arg.starts_with("--emit=") && arg.contains("metadata") && !arg.contains("link")
    });
    if not_invoked_by_build_script && is_cargo_check {
        return Ok(ExitCode(Some(0)));
    }
    run_rustc(rustc_executable, args)
}

fn run_rustc(rustc_executable: OsString, args: Vec<OsString>) -> io::Result<ExitCode> {
    let mut child = Command::new(rustc_executable)
        .args(args)
        .stdin(Stdio::inherit())
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .spawn()?;
    Ok(ExitCode(child.wait()?.code()))
}
<|endoftext|>


<commit_before>use std::vec::Vec;

pub struct Machine {
    memory: Vec<u32>,
    counter: u32,
}

impl Machine {
    pub fn new() -> Machine {
        Machine {
            memory: vec![0; 2097152],
            counter: 0,
        }
    }

    pub fn with_data(data: Vec<u32>) -> Machine {
        Machine {
            memory: data,
            counter: 0,
        }
    }

    pub fn loc(&self) -> u32 {
        self.counter
    }

    pub fn dump(&self) -> &Vec<u32> {
        &self.memory
    }

    pub fn load(&mut self, data: Vec<u32>) {
        self.memory = data;
    }

    pub fn exec(&mut self, opcode: u32, a: u32, b: u32, c: u32) {
        match opcode {
            // PC <- M[A]
            1 => {
                self.counter = self.memory[a as usize];
            },

            // If M[B] = 0, then PC <- M[A]
            2 => {
                if 0 == self.memory[b as usize] {
                  self.counter = self.memory[a as usize];
                }
            },

            // M[A] <- PC
            3 => {
                self.memory[a as usize] = self.counter;
                self.counter += 4;
            },

            // M[A] <- M[B]
            4 => {
                self.memory[a as usize] = self.memory[b as usize];
                self.counter += 4;
            },

            // M[A] <- M[M[B]]
            5 => {
                let b = self.memory[b as usize];
                self.memory[a as usize] = self.memory[b as usize];
                self.counter += 4;
            },

            // M[M[B]] <- M[A]
            6 => {
                let b = self.memory[b as usize];
                self.memory[b as usize] = self.memory[a as usize];
                self.counter += 4;
            },

            // M[A] <- M[B] + M[C]
            7 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b + c;
                self.counter += 4;
            },

            // M[A] <- M[B] - M[C]
            8 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b - c;
                self.counter += 4;
            },

            // M[A] <- M[B] x M[C]
            9 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b * c;
                self.counter += 4;
            },

            // Unknown opcode
            _ => {
            },
        }
    }
}

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

    #[test]
    fn it_loads_data() {
        let mut m = Machine::new();
        assert_eq!(Some(&0), m.dump().first());

        m.load(vec![1]);
        assert_eq!(Some(&1), m.dump().first());
    }

    #[test]
    fn it_runs_opcode_1() {
        let mut m = Machine::with_data(vec![0, 2]);

        assert_eq!(0, m.loc());
        m.exec(1, 1, 0, 0);
        assert_eq!(2, m.loc());
    }

    #[test]
    fn it_runs_opcode_2_if() {
        let mut m = Machine::with_data(vec![0, 2]);

        assert_eq!(0, m.loc());
        m.exec(2, 1, 0, 0);
        assert_eq!(2, m.loc());
    }

    #[test]
    fn it_runs_opcode_2_else() {
        let mut m = Machine::with_data(vec![1, 2]);

        assert_eq!(0, m.loc());
        m.exec(2, 1, 0, 0);
        assert_eq!(0, m.loc());
    }

    #[test]
    fn it_runs_opcode_3() {
        let mut m = Machine::with_data(vec![1]);

        assert_eq!(Some(&1), m.dump().first());
        assert_eq!(0, m.loc());
        m.exec(3, 0, 0, 0);
        assert_eq!(Some(&0), m.dump().first());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_4() {
        let mut m = Machine::with_data(vec![1, 0]);

        assert_eq!(Some(&1), m.dump().first());
        assert_eq!(0, m.loc());
        m.exec(4, 0, 1, 0);
        assert_eq!(Some(&0), m.dump().first());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_5() {
        let mut m = Machine::with_data(vec![1, 2, 0]);

        assert_eq!(Some(&1), m.dump().first());
        assert_eq!(0, m.loc());
        m.exec(5, 0, 1, 0);
        assert_eq!(Some(&0), m.dump().first());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_6() {
        let mut m = Machine::with_data(vec![1, 0]);

        assert_eq!(Some(&1), m.dump().first());
        assert_eq!(0, m.loc());
        m.exec(6, 1, 1, 0);
        assert_eq!(Some(&0), m.dump().first());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_7() {
        let mut m = Machine::with_data(vec![1, 2, 3]);

        assert_eq!(Some(&1), m.dump().first());
        assert_eq!(0, m.loc());
        m.exec(7, 0, 1, 2);
        assert_eq!(Some(&5), m.dump().first());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_8() {
        let mut m = Machine::with_data(vec![0, 3, 2]);

        assert_eq!(Some(&0), m.dump().first());
        assert_eq!(0, m.loc());
        m.exec(8, 0, 1, 2);
        assert_eq!(Some(&1), m.dump().first());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_9() {
        let mut m = Machine::with_data(vec![1, 2, 3]);

        assert_eq!(Some(&1), m.dump().first());
        assert_eq!(0, m.loc());
        m.exec(9, 0, 1, 2);
        assert_eq!(Some(&6), m.dump().first());
        assert_eq!(4, m.loc());
    }
}
<commit_msg>Test that opcode 10 works.<commit_after>use std::vec::Vec;

pub struct Machine {
    memory: Vec<u32>,
    counter: u32,
}

impl Machine {
    pub fn new() -> Machine {
        Machine {
            memory: vec![0; 2097152],
            counter: 0,
        }
    }

    pub fn with_data(data: Vec<u32>) -> Machine {
        Machine {
            memory: data,
            counter: 0,
        }
    }

    pub fn loc(&self) -> u32 {
        self.counter
    }

    pub fn dump(&self) -> &Vec<u32> {
        &self.memory
    }

    pub fn load(&mut self, data: Vec<u32>) {
        self.memory = data;
    }

    pub fn exec(&mut self, opcode: u32, a: u32, b: u32, c: u32) {
        match opcode {
            // PC <- M[A]
            1 => {
                self.counter = self.memory[a as usize];
            },

            // If M[B] = 0, then PC <- M[A]
            2 => {
                if 0 == self.memory[b as usize] {
                  self.counter = self.memory[a as usize];
                }
            },

            // M[A] <- PC
            3 => {
                self.memory[a as usize] = self.counter;
                self.counter += 4;
            },

            // M[A] <- M[B]
            4 => {
                self.memory[a as usize] = self.memory[b as usize];
                self.counter += 4;
            },

            // M[A] <- M[M[B]]
            5 => {
                let b = self.memory[b as usize];
                self.memory[a as usize] = self.memory[b as usize];
                self.counter += 4;
            },

            // M[M[B]] <- M[A]
            6 => {
                let b = self.memory[b as usize];
                self.memory[b as usize] = self.memory[a as usize];
                self.counter += 4;
            },

            // M[A] <- M[B] + M[C]
            7 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b + c;
                self.counter += 4;
            },

            // M[A] <- M[B] - M[C]
            8 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b - c;
                self.counter += 4;
            },

            // M[A] <- M[B] x M[C]
            9 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b * c;
                self.counter += 4;
            },

            // M[A] <- M[B] / M[C]
            10 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b / c;
                self.counter += 4;
            },

            // Unknown opcode
            _ => {
            },
        }
    }
}

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

    #[test]
    fn it_loads_data() {
        let mut m = Machine::new();
        assert_eq!(Some(&0), m.dump().first());

        m.load(vec![1]);
        assert_eq!(Some(&1), m.dump().first());
    }

    #[test]
    fn it_runs_opcode_1() {
        let mut m = Machine::with_data(vec![0, 2]);

        assert_eq!(0, m.loc());
        m.exec(1, 1, 0, 0);
        assert_eq!(2, m.loc());
    }

    #[test]
    fn it_runs_opcode_2_if() {
        let mut m = Machine::with_data(vec![0, 2]);

        assert_eq!(0, m.loc());
        m.exec(2, 1, 0, 0);
        assert_eq!(2, m.loc());
    }

    #[test]
    fn it_runs_opcode_2_else() {
        let mut m = Machine::with_data(vec![1, 2]);

        assert_eq!(0, m.loc());
        m.exec(2, 1, 0, 0);
        assert_eq!(0, m.loc());
    }

    #[test]
    fn it_runs_opcode_3() {
        let mut m = Machine::with_data(vec![1]);

        assert_eq!(Some(&1), m.dump().first());
        assert_eq!(0, m.loc());
        m.exec(3, 0, 0, 0);
        assert_eq!(Some(&0), m.dump().first());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_4() {
        let mut m = Machine::with_data(vec![1, 0]);

        assert_eq!(Some(&1), m.dump().first());
        assert_eq!(0, m.loc());
        m.exec(4, 0, 1, 0);
        assert_eq!(Some(&0), m.dump().first());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_5() {
        let mut m = Machine::with_data(vec![1, 2, 0]);

        assert_eq!(Some(&1), m.dump().first());
        assert_eq!(0, m.loc());
        m.exec(5, 0, 1, 0);
        assert_eq!(Some(&0), m.dump().first());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_6() {
        let mut m = Machine::with_data(vec![1, 0]);

        assert_eq!(Some(&1), m.dump().first());
        assert_eq!(0, m.loc());
        m.exec(6, 1, 1, 0);
        assert_eq!(Some(&0), m.dump().first());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_7() {
        let mut m = Machine::with_data(vec![1, 2, 3]);

        assert_eq!(Some(&1), m.dump().first());
        assert_eq!(0, m.loc());
        m.exec(7, 0, 1, 2);
        assert_eq!(Some(&5), m.dump().first());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_8() {
        let mut m = Machine::with_data(vec![0, 3, 2]);

        assert_eq!(Some(&0), m.dump().first());
        assert_eq!(0, m.loc());
        m.exec(8, 0, 1, 2);
        assert_eq!(Some(&1), m.dump().first());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_9() {
        let mut m = Machine::with_data(vec![1, 2, 3]);

        assert_eq!(Some(&1), m.dump().first());
        assert_eq!(0, m.loc());
        m.exec(9, 0, 1, 2);
        assert_eq!(Some(&6), m.dump().first());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_10() {
        let mut m = Machine::with_data(vec![1, 6, 2]);

        assert_eq!(Some(&1), m.dump().first());
        assert_eq!(0, m.loc());
        m.exec(10, 0, 1, 2);
        assert_eq!(Some(&3), m.dump().first());
        assert_eq!(4, m.loc());
    }
}
<|endoftext|>


<commit_before>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! Node manager.

use super::{encode_contract_name, to_address_vec, to_low_u64_vec};
use super::ContractCallExt;
use libexecutor::executor::Executor;
use rand::{Rng, SeedableRng, StdRng};
use rustc_hex::ToHex;
use std::cmp::Ordering;
use std::iter;
use std::str::FromStr;
use util::{Address, H160};

const LIST_NODE: &'static [u8] = &*b"listNode()";
const LIST_STAKE: &'static [u8] = *&b"listStake()";
/// Each epoch is divided into 1000 slots, each slot represent one opportunity of block proposer
const EPOCH: u64 = 1000;

lazy_static! {
    static ref LIST_NODE_ENCODED: Vec<u8> = encode_contract_name(LIST_NODE);
    static ref LIST_STAKE_ENCODED: Vec<u8> = encode_contract_name(LIST_STAKE);
    static ref CONTRACT_ADDRESS: H160 = H160::from_str("00000000000000000000000000000000013241a2").unwrap();
}

pub fn party_seats<T>(parties: Vec<T>, seats: &[u64]) -> Vec<T>
where
    T: Clone,
{
    let mut party_seats: Vec<T> = Vec::new();
    let seats_len = seats.len();
    for (index, party) in parties.into_iter().enumerate() {
        if index < seats_len {
            party_seats.extend(iter::repeat(party).take(seats[index] as usize));
        }
    }
    party_seats
}

/// https://en.wikipedia.org/wiki/Largest_remainder_method
/// Hare quota
pub fn largest_remainder_electoral(votes: &Vec<u64>, seat_number: u64) -> Vec<u64> {
    let total = votes.iter().fold(0, |acc, &x| acc + x);
    // TODO: PLS fix me!!!
    let hare_quota = total as f64 / seat_number as f64;

    let votes_quota: Vec<f64> = votes
        .iter()
        .map(|vote| (*vote as f64) / hare_quota)
        .collect();

    // calculate automatic seats first
    let mut seats: Vec<u64> = votes_quota.iter().map(|v| v.floor() as u64).collect();

    let mut remainders: Vec<(f64, u64)> = votes_quota
        .iter()
        .enumerate()
        .map(|(i, v)| (v.fract(), i as u64))
        .collect();

    let remaining_seat: u64 = seat_number - seats.iter().fold(0, |acc, &x| acc + x);

    remainders.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or(Ordering::Equal));
    remainders.reverse();

    let highest_remainder_seats: Vec<u64> = remainders
        .iter()
        .take(remaining_seat as usize)
        .map(|v| v.1)
        .collect();

    for index in highest_remainder_seats {
        seats[index as usize] += 1;
    }

    seats
}

pub struct NodeManager;

impl NodeManager {
    pub fn nodes(executor: &Executor) -> Vec<Address> {
        let output = executor.call_method_latest(&*CONTRACT_ADDRESS, &*LIST_NODE_ENCODED.as_slice());
        trace!(
            "node manager output: {:?}",
            ToHex::to_hex(output.as_slice())
        );

        let nodes: Vec<Address> = to_address_vec(&output);
        trace!("node manager nodes: {:?}", nodes);
        nodes
    }

    pub fn shuffle_node<T>(node_vec: &mut Vec<T>, rng_seed: u64) {
        let seed: &[_] = &[rng_seed as usize];
        let mut rng: StdRng = SeedableRng::from_seed(seed);

        for i in 0..node_vec.len() {
            let j: usize = rng.gen::<usize>() % (i + 1);
            node_vec.swap(i, j);
        }
    }

    pub fn stakes(executor: &Executor) -> Vec<u64> {
        let output = executor.call_method_latest(&*CONTRACT_ADDRESS, &*LIST_STAKE_ENCODED.as_slice());
        trace!("stakes output: {:?}", ToHex::to_hex(output.as_slice()));

        let stakes: Vec<u64> = to_low_u64_vec(&output);
        trace!("node manager stakes: {:?}", stakes);
        stakes
    }

    pub fn stake_nodes(exeuctor: &Executor) -> Vec<Address> {
        let nodes = NodeManager::nodes(&exeuctor);
        let stakes = NodeManager::stakes(&exeuctor);
        let total = stakes.iter().fold(0, |acc, &x| acc + x);
        let stake_nodes: Vec<Address>;

        if total == 0 {
            stake_nodes = nodes;
        } else {
            let total_seats = largest_remainder_electoral(&stakes, EPOCH);
            stake_nodes = party_seats(nodes, &total_seats);
        }
        stake_nodes
    }
=======
        }
    }
>>>>>>> c7fc76f931022b957b9dbb7dc0d8752dc5993729
}

#[cfg(test)]
mod tests {
    extern crate logger;
    extern crate mktemp;

    use super::{largest_remainder_electoral, party_seats, NodeManager};
    use std::str::FromStr;
    use tests::helpers::init_executor;
    use util::H160;

    #[test]
    fn test_node_manager_contract() {
        let executor = init_executor();
        let nodes = NodeManager::nodes(&executor);

        assert_eq!(
            nodes,
            vec![
                H160::from_str("50ad2b9d6946d9c75ae978534043e3021ee1bfb1").unwrap(),
                H160::from_str("eeb3a71c4046f63a941013f826fccc503be26b77").unwrap(),
                H160::from_str("a2bbb65d4f8c3ada29f7471abe416e18061127f3").unwrap(),
                H160::from_str("72eb1e258c9cdccebb7b62930a35cfb6ef4cd24b").unwrap(),
            ]
        )
    }

    #[test]
    fn test_largest_remainder_electoral() {
        let votes = vec![47_000, 16_000, 15_800, 12_000, 6_100, 3_100];
        let seats = 10;
        let total_seats = largest_remainder_electoral(&votes, seats);
        assert_eq!(vec![5, 2, 1, 1, 1, 0], total_seats);
    }

    #[test]
    fn test_largest_remainder_electoral_again() {
        let votes = vec![1500, 1500, 900, 500, 500, 200];
        let seats = 25;
        let total_seats = largest_remainder_electoral(&votes, seats);
        assert_eq!(vec![7, 7, 4, 3, 3, 1], total_seats);

        let new_seats = 26;
        let new_total_seats = largest_remainder_electoral(&votes, new_seats);
        assert_eq!(vec![8, 8, 5, 2, 2, 1], new_total_seats);
    }

    #[test]
    fn test_party_seats() {
        let parties = vec!["a", "b", "c"];
        let seats = vec![3, 5, 2, 2, 1];
        assert_eq!(
            party_seats(parties, &seats),
            vec!["a", "a", "a", "b", "b", "b", "b", "b", "c", "c"]
        );

        let parties = vec!["a", "b"];
        let seats = vec![2, 1];
        assert_eq!(party_seats(parties, &seats), vec!["a", "a", "b"]);

        let parties = vec!["a", "b", "c"];
        let seats = vec![2, 2];
        assert_eq!(party_seats(parties, &seats), vec!["a", "a", "b", "b"]);
    }
}
<commit_msg>[skip ci] add something missing<commit_after>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! Node manager.

use super::{encode_contract_name, to_address_vec, to_low_u64_vec};
use super::ContractCallExt;
use libexecutor::executor::Executor;
use rand::{Rng, SeedableRng, StdRng};
use rustc_hex::ToHex;
use std::cmp::Ordering;
use std::iter;
use std::str::FromStr;
use util::{Address, H160};

const LIST_NODE: &'static [u8] = &*b"listNode()";
const LIST_STAKE: &'static [u8] = *&b"listStake()";
/// Each epoch is divided into 1000 slots, each slot represent one opportunity of block proposer
const EPOCH: u64 = 1000;

lazy_static! {
    static ref LIST_NODE_ENCODED: Vec<u8> = encode_contract_name(LIST_NODE);
    static ref LIST_STAKE_ENCODED: Vec<u8> = encode_contract_name(LIST_STAKE);
    static ref CONTRACT_ADDRESS: H160 = H160::from_str("00000000000000000000000000000000013241a2").unwrap();
}

pub fn party_seats<T>(parties: Vec<T>, seats: &[u64]) -> Vec<T>
where
    T: Clone,
{
    let mut party_seats: Vec<T> = Vec::new();
    let seats_len = seats.len();
    for (index, party) in parties.into_iter().enumerate() {
        if index < seats_len {
            party_seats.extend(iter::repeat(party).take(seats[index] as usize));
        }
    }
    party_seats
}

/// https://en.wikipedia.org/wiki/Largest_remainder_method
/// Hare quota
pub fn largest_remainder_electoral(votes: &Vec<u64>, seat_number: u64) -> Vec<u64> {
    let total = votes.iter().fold(0, |acc, &x| acc + x);
    // TODO: PLS fix me!!!
    let hare_quota = total as f64 / seat_number as f64;

    let votes_quota: Vec<f64> = votes
        .iter()
        .map(|vote| (*vote as f64) / hare_quota)
        .collect();

    // calculate automatic seats first
    let mut seats: Vec<u64> = votes_quota.iter().map(|v| v.floor() as u64).collect();

    let mut remainders: Vec<(f64, u64)> = votes_quota
        .iter()
        .enumerate()
        .map(|(i, v)| (v.fract(), i as u64))
        .collect();

    let remaining_seat: u64 = seat_number - seats.iter().fold(0, |acc, &x| acc + x);

    remainders.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or(Ordering::Equal));
    remainders.reverse();

    let highest_remainder_seats: Vec<u64> = remainders
        .iter()
        .take(remaining_seat as usize)
        .map(|v| v.1)
        .collect();

    for index in highest_remainder_seats {
        seats[index as usize] += 1;
    }

    seats
}

pub struct NodeManager;

impl NodeManager {
    pub fn nodes(executor: &Executor) -> Vec<Address> {
        let output = executor.call_method_latest(&*CONTRACT_ADDRESS, &*LIST_NODE_ENCODED.as_slice());
        trace!(
            "node manager output: {:?}",
            ToHex::to_hex(output.as_slice())
        );

        let nodes: Vec<Address> = to_address_vec(&output);
        trace!("node manager nodes: {:?}", nodes);
        nodes
    }

    pub fn shuffle_node<T>(node_vec: &mut Vec<T>, rng_seed: u64) {
        let seed: &[_] = &[rng_seed as usize];
        let mut rng: StdRng = SeedableRng::from_seed(seed);

        for i in 0..node_vec.len() {
            let j: usize = rng.gen::<usize>() % (i + 1);
            node_vec.swap(i, j);
        }
    }

    pub fn stakes(executor: &Executor) -> Vec<u64> {
        let output = executor.call_method_latest(&*CONTRACT_ADDRESS, &*LIST_STAKE_ENCODED.as_slice());
        trace!("stakes output: {:?}", ToHex::to_hex(output.as_slice()));

        let stakes: Vec<u64> = to_low_u64_vec(&output);
        trace!("node manager stakes: {:?}", stakes);
        stakes
    }

    pub fn stake_nodes(exeuctor: &Executor) -> Vec<Address> {
        let nodes = NodeManager::nodes(&exeuctor);
        let stakes = NodeManager::stakes(&exeuctor);
        let total = stakes.iter().fold(0, |acc, &x| acc + x);
        let stake_nodes: Vec<Address>;

        if total == 0 {
            stake_nodes = nodes;
        } else {
            let total_seats = largest_remainder_electoral(&stakes, EPOCH);
            stake_nodes = party_seats(nodes, &total_seats);
        }
        stake_nodes
    }
}

#[cfg(test)]
mod tests {
    extern crate logger;
    extern crate mktemp;

    use super::{largest_remainder_electoral, party_seats, NodeManager};
    use std::str::FromStr;
    use tests::helpers::init_executor;
    use util::H160;

    #[test]
    fn test_node_manager_contract() {
        let executor = init_executor();
        let nodes = NodeManager::nodes(&executor);

        assert_eq!(
            nodes,
            vec![
                H160::from_str("50ad2b9d6946d9c75ae978534043e3021ee1bfb1").unwrap(),
                H160::from_str("eeb3a71c4046f63a941013f826fccc503be26b77").unwrap(),
                H160::from_str("a2bbb65d4f8c3ada29f7471abe416e18061127f3").unwrap(),
                H160::from_str("72eb1e258c9cdccebb7b62930a35cfb6ef4cd24b").unwrap(),
            ]
        )
    }

    #[test]
    fn test_largest_remainder_electoral() {
        let votes = vec![47_000, 16_000, 15_800, 12_000, 6_100, 3_100];
        let seats = 10;
        let total_seats = largest_remainder_electoral(&votes, seats);
        assert_eq!(vec![5, 2, 1, 1, 1, 0], total_seats);
    }

    #[test]
    fn test_largest_remainder_electoral_again() {
        let votes = vec![1500, 1500, 900, 500, 500, 200];
        let seats = 25;
        let total_seats = largest_remainder_electoral(&votes, seats);
        assert_eq!(vec![7, 7, 4, 3, 3, 1], total_seats);

        let new_seats = 26;
        let new_total_seats = largest_remainder_electoral(&votes, new_seats);
        assert_eq!(vec![8, 8, 5, 2, 2, 1], new_total_seats);
    }

    #[test]
    fn test_party_seats() {
        let parties = vec!["a", "b", "c"];
        let seats = vec![3, 5, 2, 2, 1];
        assert_eq!(
            party_seats(parties, &seats),
            vec!["a", "a", "a", "b", "b", "b", "b", "b", "c", "c"]
        );

        let parties = vec!["a", "b"];
        let seats = vec![2, 1];
        assert_eq!(party_seats(parties, &seats), vec!["a", "a", "b"]);

        let parties = vec!["a", "b", "c"];
        let seats = vec![2, 2];
        assert_eq!(party_seats(parties, &seats), vec!["a", "a", "b", "b"]);
    }
}
<|endoftext|>


<commit_before>use json;

struct Message {
    pub message_id: i32,
    pub from: Option<String>,  // TODO: Change to User struct
    pub date: i32,
    pub chat: String,  // TODO: Change to Chat struct
    pub forward_from: Option<String>,  // TODO: Change to User struct
    pub forward_from_chat: Option<String>,  // TODO: Change to Chat struct
    pub forward_from_message_id: Option<i32>,
    pub forward_date: Option<i32>,
    pub reply_to_message: Option<Box<Message>>,
    pub edit_date: Option<i32>,
    pub text: Option<String>,
    pub entities: Option<String>,  // TODO: Change to MessageEntity struct
    pub audio: Option<String>,  // TODO: Change to audio struct
    pub document: Option<String>,  // TODO: Change to Document struct
    pub game: Option<String>,  // TODO: Change to Game struct
    pub photo: Option<String>,  // TODO: Change to Photo struct
    pub sticker: Option<String>,  // TODO: Change to Sticker struct
    pub video: Option<String>,  // TODO: Change to Video struct
    pub voice: Option<String>,  // TODO: Change to Voice struct
    pub caption: Option<String>,
    pub contact: Option<String>,  // TODO: Change to Contact struct
    pub location: Option<String>,  // TODO: Change to Location struct
    pub venue: Option<String>,  // TODO: Change to Venue struct
    pub new_chat_member: Option<String>,  // TODO: Change to User struct
    pub left_chat_member: Option<String>,  // TODO: Change to User struct
    pub new_chat_title: Option<String>,
    pub new_chat_photo: Option<String>,  // TODO: Change to array of Photo structs
    pub delete_chat_photo: Option<bool>,
    pub group_chat_created: Option<bool>,
    pub supergroup_chat_created: Option<bool>,
    pub channel_chat_created: Option<bool>,
    pub migrate_to_chat_id: Option<i32>,
    pub migrate_from_chat_id: Option<i32>,
    pub pinned_message: Option<String>,  // TODO: Change to Message struct
}

impl Message {
    pub fn new(rjson: json::JsonValue) -> Message {
        unimplemented!();
    }
}
<commit_msg>Adding a constructor.<commit_after>use json;

pub struct Message {
    pub message_id: i32,
    pub from: Option<String>,  // TODO: Change to User struct
    pub date: i32,
    pub chat: String,  // TODO: Change to Chat struct
    pub forward_from: Option<String>,  // TODO: Change to User struct
    pub forward_from_chat: Option<String>,  // TODO: Change to Chat struct
    pub forward_from_message_id: Option<i32>,
    pub forward_date: Option<i32>,
    pub reply_to_message: Option<Box<Message>>,
    pub edit_date: Option<i32>,
    pub text: Option<String>,
    pub entities: Option<String>,  // TODO: Change to MessageEntity struct
    pub audio: Option<String>,  // TODO: Change to audio struct
    pub document: Option<String>,  // TODO: Change to Document struct
    pub game: Option<String>,  // TODO: Change to Game struct
    pub photo: Option<String>,  // TODO: Change to Photo struct
    pub sticker: Option<String>,  // TODO: Change to Sticker struct
    pub video: Option<String>,  // TODO: Change to Video struct
    pub voice: Option<String>,  // TODO: Change to Voice struct
    pub caption: Option<String>,
    pub contact: Option<String>,  // TODO: Change to Contact struct
    pub location: Option<String>,  // TODO: Change to Location struct
    pub venue: Option<String>,  // TODO: Change to Venue struct
    pub new_chat_member: Option<String>,  // TODO: Change to User struct
    pub left_chat_member: Option<String>,  // TODO: Change to User struct
    pub new_chat_title: Option<String>,
    pub new_chat_photo: Option<String>,  // TODO: Change to array of Photo structs
    pub delete_chat_photo: Option<bool>,
    pub group_chat_created: Option<bool>,
    pub supergroup_chat_created: Option<bool>,
    pub channel_chat_created: Option<bool>,
    pub migrate_to_chat_id: Option<i32>,
    pub migrate_from_chat_id: Option<i32>,
    pub pinned_message: Option<String>,  // TODO: Change to Message struct
}

impl Message {
    pub fn new(rjson: json::JsonValue) -> Message {
        unimplemented!();
    }
}
<|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/. */

// NOTE: https://www.chromium.org/directwrite-font-proxy has useful
// information for an approach that we'll likely need to take when the
// renderer moves to a sandboxed process.

use app_units::Au;
use dwrote;
use dwrote::{Font, FontFace, FontFile};
use dwrote::{FontWeight, FontStretch, FontStyle};
use font::{FontHandleMethods, FontMetrics, FontTableMethods};
use font::{FontTableTag, FractionalPixel};
use platform::font_template::FontTemplateData;
use platform::windows::font_context::FontContextHandle;
use platform::windows::font_list::font_from_atom;
use std::sync::Arc;
use style::computed_values::{font_stretch, font_weight};
use text::glyph::GlyphId;
use truetype;

// 1em = 12pt = 16px, assuming 72 points per inch and 96 px per inch
fn pt_to_px(pt: f64) -> f64 { pt / 72. * 96. }
fn em_to_px(em: f64) -> f64 { em * 16. }
fn au_from_em(em: f64) -> Au { Au::from_f64_px(em_to_px(em)) }
fn au_from_pt(pt: f64) -> Au { Au::from_f64_px(pt_to_px(pt)) }

pub struct FontTable {
    data: Vec<u8>,
}

impl FontTable {
    pub fn wrap(data: &[u8]) -> FontTable {
        FontTable { data: data.to_vec() }
    }
}

impl FontTableMethods for FontTable {
    fn buffer(&self) -> &[u8] {
        &self.data
    }
}

fn make_tag(tag_bytes: &[u8]) -> FontTableTag {
    assert_eq!(tag_bytes.len(), 4);
    unsafe { *(tag_bytes.as_ptr() as *const FontTableTag) }
}

macro_rules! try_lossy(($result:expr) => (try!($result.map_err(|_| (())))));

// Given a set of records, figure out the string indices for the family and face
// names.  We want name_id 1 and 2, and we need to use platform_id == 1 and
// language_id == 0 to avoid limitations in the truetype crate.  We *could* just
// do our own parsing here, and use the offset/length data and pull the values out
// ourselves.
fn get_family_face_indices(records: &[truetype::naming_table::Record]) -> Option<(usize, usize)> {
    let mut family_name_index = None;
    let mut face_name_index = None;

    for i in 0..records.len() {
        // the truetype crate can only decode mac platform format names
        if records[i].platform_id != 1 {
            continue;
        }

        if records[i].language_id != 0 {
            continue;
        }

        if records[i].name_id == 1 {
            family_name_index = Some(i);
        } else if records[i].name_id == 2 {
            face_name_index = Some(i);
        }
    }

    if family_name_index.is_some() && face_name_index.is_some() {
        Some((family_name_index.unwrap(), face_name_index.unwrap()))
    } else {
        None
    }
}

// We need the font (DWriteFont) in order to be able to query things like
// the family name, face name, weight, etc.  On Windows 10, the
// DWriteFontFace3 interface provides this on the FontFace, but that's only
// available on Win10+.
//
// Instead, we do the parsing work using the truetype crate for raw fonts.
// We're just extracting basic info, so this is sufficient for now.

#[derive(Debug)]
struct FontInfo {
    family_name: String,
    face_name: String,
    weight: font_weight::T,
    stretch: font_stretch::T,
    style: FontStyle,
}

impl FontInfo {
    fn new_from_face(face: &FontFace) -> Result<FontInfo, ()> {
        use std::cmp::{min, max};
        use std::io::Cursor;
        use truetype::{NamingTable, Value, WindowsMetrics};

        let name_table_bytes = face.get_font_table(make_tag(b"name"));
        let os2_table_bytes = face.get_font_table(make_tag(b"OS/2"));
        if name_table_bytes.is_none() || os2_table_bytes.is_none() {
            return Err(());
        }

        let mut name_table_cursor = Cursor::new(name_table_bytes.as_ref().unwrap());
        let names = try_lossy!(NamingTable::read(&mut name_table_cursor));
        let (family, face) = match names {
            NamingTable::Format0(ref table) => {
                if let Some((family_index, face_index)) = get_family_face_indices(&table.records) {
                    let strings = table.strings().unwrap();
                    let family = strings[family_index].clone();
                    let face = strings[face_index].clone();
                    ((family, face))
                } else {
                    return Err(());
                }
            },
            NamingTable::Format1(ref table) => {
                if let Some((family_index, face_index)) = get_family_face_indices(&table.records) {
                    let strings = table.strings().unwrap();
                    let family = strings[family_index].clone();
                    let face = strings[face_index].clone();
                    ((family, face))
                } else {
                    return Err(());
                }
            }
        };

        let mut os2_table_cursor = Cursor::new(os2_table_bytes.as_ref().unwrap());
        let metrics = try_lossy!(WindowsMetrics::read(&mut os2_table_cursor));
        let (weight_val, width_val, italic_bool) = match metrics {
            WindowsMetrics::Version0(ref m) => {
                (m.weight_class, m.width_class, m.selection_flags.0 & 1 == 1)
            },
            WindowsMetrics::Version1(ref m) => {
                (m.weight_class, m.width_class, m.selection_flags.0 & 1 == 1)
            },
            WindowsMetrics::Version2(ref m) |
            WindowsMetrics::Version3(ref m) |
            WindowsMetrics::Version4(ref m) => {
                (m.weight_class, m.width_class, m.selection_flags.0 & 1 == 1)
            },
            WindowsMetrics::Version5(ref m) => {
                (m.weight_class, m.width_class, m.selection_flags.0 & 1 == 1)
            },
        };

        let weight = match min(9, max(1, weight_val / 100)) {
            1 => font_weight::T::Weight100,
            2 => font_weight::T::Weight200,
            3 => font_weight::T::Weight300,
            4 => font_weight::T::Weight400,
            5 => font_weight::T::Weight500,
            6 => font_weight::T::Weight600,
            7 => font_weight::T::Weight700,
            8 => font_weight::T::Weight800,
            9 => font_weight::T::Weight900,
            _ => return Err(()),
        };

        let stretch = match min(9, max(1, width_val)) {
            1 => font_stretch::T::ultra_condensed,
            2 => font_stretch::T::extra_condensed,
            3 => font_stretch::T::condensed,
            4 => font_stretch::T::semi_condensed,
            5 => font_stretch::T::normal,
            6 => font_stretch::T::semi_expanded,
            7 => font_stretch::T::expanded,
            8 => font_stretch::T::extra_expanded,
            9 => font_stretch::T::ultra_expanded,
            _ => return Err(()),
        };

        let style = if italic_bool {
            FontStyle::Italic
        } else {
            FontStyle::Normal
        };

        Ok(FontInfo {
            family_name: family,
            face_name: face,
            weight: weight,
            stretch: stretch,
            style: style,
        })
    }

    fn new_from_font(font: &Font) -> Result<FontInfo, ()> {
        let style = font.style();
        let weight = match font.weight() {
            FontWeight::Thin => font_weight::T::Weight100,
            FontWeight::ExtraLight => font_weight::T::Weight200,
            FontWeight::Light => font_weight::T::Weight300,
            // slightly grayer gray
            FontWeight::SemiLight => font_weight::T::Weight300,
            FontWeight::Regular => font_weight::T::Weight400,
            FontWeight::Medium => font_weight::T::Weight500,
            FontWeight::SemiBold => font_weight::T::Weight600,
            FontWeight::Bold => font_weight::T::Weight700,
            FontWeight::ExtraBold => font_weight::T::Weight800,
            FontWeight::Black => font_weight::T::Weight900,
            // slightly blacker black
            FontWeight::ExtraBlack => font_weight::T::Weight900,
        };
        let stretch = match font.stretch() {
            FontStretch::Undefined => font_stretch::T::normal,
            FontStretch::UltraCondensed => font_stretch::T::ultra_condensed,
            FontStretch::ExtraCondensed => font_stretch::T::extra_condensed,
            FontStretch::Condensed => font_stretch::T::condensed,
            FontStretch::SemiCondensed => font_stretch::T::semi_condensed,
            FontStretch::Normal => font_stretch::T::normal,
            FontStretch::SemiExpanded => font_stretch::T::semi_expanded,
            FontStretch::Expanded => font_stretch::T::expanded,
            FontStretch::ExtraExpanded => font_stretch::T::extra_expanded,
            FontStretch::UltraExpanded => font_stretch::T::ultra_expanded,
        };

        Ok(FontInfo {
            family_name: font.family_name(),
            face_name: font.face_name(),
            style: style,
            weight: weight,
            stretch: stretch,
        })
    }
}

#[derive(Debug)]
pub struct FontHandle {
    font_data: Arc<FontTemplateData>,
    face: FontFace,
    info: FontInfo,
    em_size: f32,
    du_per_em: f32,
    du_to_px: f32,
    scaled_du_to_px: f32,
}

impl FontHandle {
}

impl FontHandleMethods for FontHandle {
    fn new_from_template(_: &FontContextHandle, template: Arc<FontTemplateData>, pt_size: Option<Au>)
                         -> Result<Self, ()>
    {
        let (info, face) = if let Some(ref raw_font) = template.bytes {
            let font_file = FontFile::new_from_data(&raw_font);
            if font_file.is_none() {
                // failed to load raw font
                return Err(());
            }

            let face = font_file.unwrap().create_face(0, dwrote::DWRITE_FONT_SIMULATIONS_NONE);
            let info = try!(FontInfo::new_from_face(&face));
            (info, face)
        } else {
            let font = font_from_atom(&template.identifier);
            let face = font.create_font_face();
            let info = try!(FontInfo::new_from_font(&font));
            (info, face)
        };

        let pt_size = pt_size.unwrap_or(au_from_pt(12.));
        let du_per_em = face.metrics().designUnitsPerEm as f32;

        let em_size = pt_size.to_f32_px() / 16.;
        let design_units_per_pixel = du_per_em / 16.;

        let design_units_to_pixels = 1. / design_units_per_pixel;
        let scaled_design_units_to_pixels = em_size / design_units_per_pixel;

        Ok(FontHandle {
            font_data: template.clone(),
            face: face,
            info: info,
            em_size: em_size,
            du_per_em: du_per_em,
            du_to_px: design_units_to_pixels,
            scaled_du_to_px: scaled_design_units_to_pixels,
        })
    }

    fn template(&self) -> Arc<FontTemplateData> {
        self.font_data.clone()
    }

    fn family_name(&self) -> String {
        self.info.family_name.clone()
    }

    fn face_name(&self) -> String {
        self.info.face_name.clone()
    }

    fn is_italic(&self) -> bool {
        match self.info.style {
            FontStyle::Normal => false,
            FontStyle::Oblique | FontStyle::Italic => true,
        }
    }

    fn boldness(&self) -> font_weight::T {
        self.info.weight
    }

    fn stretchiness(&self) -> font_stretch::T {
        self.info.stretch
    }

    fn glyph_index(&self, codepoint: char) -> Option<GlyphId> {
        let glyph = self.face.get_glyph_indices(&[codepoint as u32])[0];
        if glyph == 0 {
            return None;
        }
        Some(glyph as GlyphId)
    }

    fn glyph_h_advance(&self, glyph: GlyphId) -> Option<FractionalPixel> {
        if glyph == 0 {
            return None;
        }

        let gm = self.face.get_design_glyph_metrics(&[glyph as u16], false)[0];
        let f = (gm.advanceWidth as f32 * self.scaled_du_to_px) as FractionalPixel;

        Some(f)
    }

    /// Can this font do basic horizontal LTR shaping without Harfbuzz?
    fn can_do_fast_shaping(&self) -> bool {
        // TODO copy CachedKernTable from the MacOS X implementation to
        // somehwere global and use it here.  We could also implement the
        // IDirectWriteFontFace1 interface and use the glyph kerning pair
        // methods there.
        false
    }

    fn glyph_h_kerning(&self, _: GlyphId, _: GlyphId) -> FractionalPixel {
        0.0
    }

    fn metrics(&self) -> FontMetrics {
        let dm = self.face.metrics();

        let au_from_du = |du| -> Au { Au::from_f32_px(du as f32 * self.du_to_px) };
        let au_from_du_s = |du| -> Au { Au:: from_f32_px(du as f32 * self.scaled_du_to_px) };

        // anything that we calculate and don't just pull out of self.face.metrics
        // is pulled out here for clarity
        let leading = dm.ascent - dm.capHeight;

        let metrics = FontMetrics {
            underline_size:   au_from_du(dm.underlineThickness as i32),
            underline_offset: au_from_du_s(dm.underlinePosition as i32),
            strikeout_size:   au_from_du(dm.strikethroughThickness as i32),
            strikeout_offset: au_from_du_s(dm.strikethroughPosition as i32),
            leading:          au_from_du_s(leading as i32),
            x_height:         au_from_du_s(dm.xHeight as i32),
            em_size:          au_from_em(self.em_size as f64),
            ascent:           au_from_du_s(dm.ascent as i32),
            descent:          au_from_du_s(dm.descent as i32),
            max_advance:      au_from_pt(0.0), // FIXME
            average_advance:  au_from_pt(0.0), // FIXME
            line_gap:         au_from_du(dm.lineGap as i32),
        };
        debug!("Font metrics (@{} pt): {:?}", self.em_size * 12., metrics);
        metrics
    }

    fn table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> {
        self.face.get_font_table(tag).map(|bytes| FontTable { data: bytes })
    }
}
<commit_msg>Change windows font metrics<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/. */

// NOTE: https://www.chromium.org/directwrite-font-proxy has useful
// information for an approach that we'll likely need to take when the
// renderer moves to a sandboxed process.

use app_units::Au;
use dwrote;
use dwrote::{Font, FontFace, FontFile};
use dwrote::{FontWeight, FontStretch, FontStyle};
use font::{FontHandleMethods, FontMetrics, FontTableMethods};
use font::{FontTableTag, FractionalPixel};
use platform::font_template::FontTemplateData;
use platform::windows::font_context::FontContextHandle;
use platform::windows::font_list::font_from_atom;
use std::sync::Arc;
use style::computed_values::{font_stretch, font_weight};
use text::glyph::GlyphId;
use truetype;

// 1em = 12pt = 16px, assuming 72 points per inch and 96 px per inch
fn pt_to_px(pt: f64) -> f64 { pt / 72. * 96. }
fn em_to_px(em: f64) -> f64 { em * 16. }
fn au_from_em(em: f64) -> Au { Au::from_f64_px(em_to_px(em)) }
fn au_from_pt(pt: f64) -> Au { Au::from_f64_px(pt_to_px(pt)) }

pub struct FontTable {
    data: Vec<u8>,
}

impl FontTable {
    pub fn wrap(data: &[u8]) -> FontTable {
        FontTable { data: data.to_vec() }
    }
}

impl FontTableMethods for FontTable {
    fn buffer(&self) -> &[u8] {
        &self.data
    }
}

fn make_tag(tag_bytes: &[u8]) -> FontTableTag {
    assert_eq!(tag_bytes.len(), 4);
    unsafe { *(tag_bytes.as_ptr() as *const FontTableTag) }
}

macro_rules! try_lossy(($result:expr) => (try!($result.map_err(|_| (())))));

// Given a set of records, figure out the string indices for the family and face
// names.  We want name_id 1 and 2, and we need to use platform_id == 1 and
// language_id == 0 to avoid limitations in the truetype crate.  We *could* just
// do our own parsing here, and use the offset/length data and pull the values out
// ourselves.
fn get_family_face_indices(records: &[truetype::naming_table::Record]) -> Option<(usize, usize)> {
    let mut family_name_index = None;
    let mut face_name_index = None;

    for i in 0..records.len() {
        // the truetype crate can only decode mac platform format names
        if records[i].platform_id != 1 {
            continue;
        }

        if records[i].language_id != 0 {
            continue;
        }

        if records[i].name_id == 1 {
            family_name_index = Some(i);
        } else if records[i].name_id == 2 {
            face_name_index = Some(i);
        }
    }

    if family_name_index.is_some() && face_name_index.is_some() {
        Some((family_name_index.unwrap(), face_name_index.unwrap()))
    } else {
        None
    }
}

// We need the font (DWriteFont) in order to be able to query things like
// the family name, face name, weight, etc.  On Windows 10, the
// DWriteFontFace3 interface provides this on the FontFace, but that's only
// available on Win10+.
//
// Instead, we do the parsing work using the truetype crate for raw fonts.
// We're just extracting basic info, so this is sufficient for now.

#[derive(Debug)]
struct FontInfo {
    family_name: String,
    face_name: String,
    weight: font_weight::T,
    stretch: font_stretch::T,
    style: FontStyle,
}

impl FontInfo {
    fn new_from_face(face: &FontFace) -> Result<FontInfo, ()> {
        use std::cmp::{min, max};
        use std::io::Cursor;
        use truetype::{NamingTable, Value, WindowsMetrics};

        let name_table_bytes = face.get_font_table(make_tag(b"name"));
        let os2_table_bytes = face.get_font_table(make_tag(b"OS/2"));
        if name_table_bytes.is_none() || os2_table_bytes.is_none() {
            return Err(());
        }

        let mut name_table_cursor = Cursor::new(name_table_bytes.as_ref().unwrap());
        let names = try_lossy!(NamingTable::read(&mut name_table_cursor));
        let (family, face) = match names {
            NamingTable::Format0(ref table) => {
                if let Some((family_index, face_index)) = get_family_face_indices(&table.records) {
                    let strings = table.strings().unwrap();
                    let family = strings[family_index].clone();
                    let face = strings[face_index].clone();
                    ((family, face))
                } else {
                    return Err(());
                }
            },
            NamingTable::Format1(ref table) => {
                if let Some((family_index, face_index)) = get_family_face_indices(&table.records) {
                    let strings = table.strings().unwrap();
                    let family = strings[family_index].clone();
                    let face = strings[face_index].clone();
                    ((family, face))
                } else {
                    return Err(());
                }
            }
        };

        let mut os2_table_cursor = Cursor::new(os2_table_bytes.as_ref().unwrap());
        let metrics = try_lossy!(WindowsMetrics::read(&mut os2_table_cursor));
        let (weight_val, width_val, italic_bool) = match metrics {
            WindowsMetrics::Version0(ref m) => {
                (m.weight_class, m.width_class, m.selection_flags.0 & 1 == 1)
            },
            WindowsMetrics::Version1(ref m) => {
                (m.weight_class, m.width_class, m.selection_flags.0 & 1 == 1)
            },
            WindowsMetrics::Version2(ref m) |
            WindowsMetrics::Version3(ref m) |
            WindowsMetrics::Version4(ref m) => {
                (m.weight_class, m.width_class, m.selection_flags.0 & 1 == 1)
            },
            WindowsMetrics::Version5(ref m) => {
                (m.weight_class, m.width_class, m.selection_flags.0 & 1 == 1)
            },
        };

        let weight = match min(9, max(1, weight_val / 100)) {
            1 => font_weight::T::Weight100,
            2 => font_weight::T::Weight200,
            3 => font_weight::T::Weight300,
            4 => font_weight::T::Weight400,
            5 => font_weight::T::Weight500,
            6 => font_weight::T::Weight600,
            7 => font_weight::T::Weight700,
            8 => font_weight::T::Weight800,
            9 => font_weight::T::Weight900,
            _ => return Err(()),
        };

        let stretch = match min(9, max(1, width_val)) {
            1 => font_stretch::T::ultra_condensed,
            2 => font_stretch::T::extra_condensed,
            3 => font_stretch::T::condensed,
            4 => font_stretch::T::semi_condensed,
            5 => font_stretch::T::normal,
            6 => font_stretch::T::semi_expanded,
            7 => font_stretch::T::expanded,
            8 => font_stretch::T::extra_expanded,
            9 => font_stretch::T::ultra_expanded,
            _ => return Err(()),
        };

        let style = if italic_bool {
            FontStyle::Italic
        } else {
            FontStyle::Normal
        };

        Ok(FontInfo {
            family_name: family,
            face_name: face,
            weight: weight,
            stretch: stretch,
            style: style,
        })
    }

    fn new_from_font(font: &Font) -> Result<FontInfo, ()> {
        let style = font.style();
        let weight = match font.weight() {
            FontWeight::Thin => font_weight::T::Weight100,
            FontWeight::ExtraLight => font_weight::T::Weight200,
            FontWeight::Light => font_weight::T::Weight300,
            // slightly grayer gray
            FontWeight::SemiLight => font_weight::T::Weight300,
            FontWeight::Regular => font_weight::T::Weight400,
            FontWeight::Medium => font_weight::T::Weight500,
            FontWeight::SemiBold => font_weight::T::Weight600,
            FontWeight::Bold => font_weight::T::Weight700,
            FontWeight::ExtraBold => font_weight::T::Weight800,
            FontWeight::Black => font_weight::T::Weight900,
            // slightly blacker black
            FontWeight::ExtraBlack => font_weight::T::Weight900,
        };
        let stretch = match font.stretch() {
            FontStretch::Undefined => font_stretch::T::normal,
            FontStretch::UltraCondensed => font_stretch::T::ultra_condensed,
            FontStretch::ExtraCondensed => font_stretch::T::extra_condensed,
            FontStretch::Condensed => font_stretch::T::condensed,
            FontStretch::SemiCondensed => font_stretch::T::semi_condensed,
            FontStretch::Normal => font_stretch::T::normal,
            FontStretch::SemiExpanded => font_stretch::T::semi_expanded,
            FontStretch::Expanded => font_stretch::T::expanded,
            FontStretch::ExtraExpanded => font_stretch::T::extra_expanded,
            FontStretch::UltraExpanded => font_stretch::T::ultra_expanded,
        };

        Ok(FontInfo {
            family_name: font.family_name(),
            face_name: font.face_name(),
            style: style,
            weight: weight,
            stretch: stretch,
        })
    }
}

#[derive(Debug)]
pub struct FontHandle {
    font_data: Arc<FontTemplateData>,
    face: FontFace,
    info: FontInfo,
    em_size: f32,
    du_per_em: f32,
    du_to_px: f32,
    scaled_du_to_px: f32,
}

impl FontHandle {
}

impl FontHandleMethods for FontHandle {
    fn new_from_template(_: &FontContextHandle, template: Arc<FontTemplateData>, pt_size: Option<Au>)
                         -> Result<Self, ()>
    {
        let (info, face) = if let Some(ref raw_font) = template.bytes {
            let font_file = FontFile::new_from_data(&raw_font);
            if font_file.is_none() {
                // failed to load raw font
                return Err(());
            }

            let face = font_file.unwrap().create_face(0, dwrote::DWRITE_FONT_SIMULATIONS_NONE);
            let info = try!(FontInfo::new_from_face(&face));
            (info, face)
        } else {
            let font = font_from_atom(&template.identifier);
            let face = font.create_font_face();
            let info = try!(FontInfo::new_from_font(&font));
            (info, face)
        };

        let pt_size = pt_size.unwrap_or(au_from_pt(12.));
        let du_per_em = face.metrics().designUnitsPerEm as f32;

        let em_size = pt_size.to_f32_px() / 16.;
        let design_units_per_pixel = du_per_em / 16.;

        let design_units_to_pixels = 1. / design_units_per_pixel;
        let scaled_design_units_to_pixels = em_size / design_units_per_pixel;

        Ok(FontHandle {
            font_data: template.clone(),
            face: face,
            info: info,
            em_size: em_size,
            du_per_em: du_per_em,
            du_to_px: design_units_to_pixels,
            scaled_du_to_px: scaled_design_units_to_pixels,
        })
    }

    fn template(&self) -> Arc<FontTemplateData> {
        self.font_data.clone()
    }

    fn family_name(&self) -> String {
        self.info.family_name.clone()
    }

    fn face_name(&self) -> String {
        self.info.face_name.clone()
    }

    fn is_italic(&self) -> bool {
        match self.info.style {
            FontStyle::Normal => false,
            FontStyle::Oblique | FontStyle::Italic => true,
        }
    }

    fn boldness(&self) -> font_weight::T {
        self.info.weight
    }

    fn stretchiness(&self) -> font_stretch::T {
        self.info.stretch
    }

    fn glyph_index(&self, codepoint: char) -> Option<GlyphId> {
        let glyph = self.face.get_glyph_indices(&[codepoint as u32])[0];
        if glyph == 0 {
            return None;
        }
        Some(glyph as GlyphId)
    }

    fn glyph_h_advance(&self, glyph: GlyphId) -> Option<FractionalPixel> {
        if glyph == 0 {
            return None;
        }

        let gm = self.face.get_design_glyph_metrics(&[glyph as u16], false)[0];
        let f = (gm.advanceWidth as f32 * self.scaled_du_to_px) as FractionalPixel;

        Some(f)
    }

    /// Can this font do basic horizontal LTR shaping without Harfbuzz?
    fn can_do_fast_shaping(&self) -> bool {
        // TODO copy CachedKernTable from the MacOS X implementation to
        // somehwere global and use it here.  We could also implement the
        // IDirectWriteFontFace1 interface and use the glyph kerning pair
        // methods there.
        false
    }

    fn glyph_h_kerning(&self, _: GlyphId, _: GlyphId) -> FractionalPixel {
        0.0
    }

    fn metrics(&self) -> FontMetrics {
        let dm = self.face.metrics();

        let au_from_du = |du| -> Au { Au::from_f32_px(du as f32 * self.du_to_px) };
        let au_from_du_s = |du| -> Au { Au:: from_f32_px(du as f32 * self.scaled_du_to_px) };

        // anything that we calculate and don't just pull out of self.face.metrics
        // is pulled out here for clarity
        let leading = dm.ascent - dm.capHeight;

        let metrics = FontMetrics {
            underline_size:   au_from_du(dm.underlineThickness as i32),
            underline_offset: au_from_du_s(dm.underlinePosition as i32),
            strikeout_size:   au_from_du(dm.strikethroughThickness as i32),
            strikeout_offset: au_from_du_s(dm.strikethroughPosition as i32),
            leading:          au_from_du_s(leading as i32),
            x_height:         au_from_du_s(dm.xHeight as i32),
            em_size:          au_from_em(self.em_size as f64),
            ascent:           au_from_du_s(dm.ascent as i32),
            descent:          au_from_du_s(dm.descent as i32),
            max_advance:      au_from_pt(0.0), // FIXME
            average_advance:  au_from_pt(0.0), // FIXME
            line_gap:         au_from_du((dm.ascent + dm.descent + dm.lineGap as u16) as i32),
        };
        debug!("Font metrics (@{} pt): {:?}", self.em_size * 12., metrics);
        metrics
    }

    fn table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> {
        self.face.get_font_table(tag).map(|bytes| FontTable { data: bytes })
    }
}
<|endoftext|>