<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*!
Driver for C12332 LCD.

C12332 is black&white LCD, the only supported color value is `1`. The LCD is
buffered in driver memory.

The driver uses SPI bus for output only, it never reads back from SPI, which
might be an issue for any other peripheral sharing the same SPI bus.
*/

use core::cell;
use core::slice::SliceExt;
use core::mem::zeroed;
use core::iter::range;

use super::font_small_7;
use super::LCD;
use drivers::chario::CharIO;
use hal::timer::Timer;
use hal::pin::Gpio;
use hal::spi::Spi;

/// C12332 driver.
pub struct C12332<'a, S:'a, T:'a, P:'a> {
  spi: &'a S,
  timer: &'a T,

  dc:    &'a P,
  cs:    &'a P,
  reset: &'a P,

  videobuf: [cell::Cell<u8>; 512],

  font: &'static [u8],
  char_x: cell::Cell<u32>,
  char_y: cell::Cell<u32>,
}

impl<'a, S: Spi, T: Timer, P: Gpio> C12332<'a, S, T, P> {
  /// Creates a new C12332 driver instance.
  pub fn new(spi: &'a S, timer: &'a T, dc: &'a P, cs: &'a P,
      reset: &'a P) -> C12332<'a, S, T, P> {
    let lcd = C12332 {
      spi:   spi,
      timer: timer,
      dc:    dc,
      cs:    cs,
      reset: reset,

      videobuf: unsafe { zeroed() },

      font: font_small_7::FONT,
      char_x: cell::Cell::new(0),
      char_y: cell::Cell::new(0),
    };

    lcd.configure();

    lcd
  }

  fn configure(&self) {
    self.dc.set_low();
    self.cs.set_high();
    self.reset.set_low();
    self.timer.wait_us(50);
    self.reset.set_high();
    self.timer.wait_ms(5);

    self.wr_cmd(0xAE);   //  display off
    self.wr_cmd(0xA2);   //  bias voltage

    self.wr_cmd(0xA0);
    self.wr_cmd(0xC8);   //  colum normal

    self.wr_cmd(0x22);   //  voltage resistor ratio
    self.wr_cmd(0x2F);   //  power on
    //self.wr_cmd(0xA4);   //  LCD display ram
    self.wr_cmd(0x40);   // start line = 0
    self.wr_cmd(0xAF);     // display ON

    self.wr_cmd(0x81);   //  set contrast
    self.wr_cmd(0x17);   //  set contrast

    self.wr_cmd(0xA6);     // display normal

    (self as &LCD).flush();
  }

  fn wr_cmd(&self, cmd: u8) {
    self.dc.set_low();
    self.cs.set_low();
    self.spi.write(cmd);
    self.cs.set_high();
  }

  fn wr_dat(&self, cmd: u8) {
    self.dc.set_high();
    self.cs.set_low();
    self.spi.write(cmd);
    self.cs.set_high();
  }

  /// Sets an individual pixel.
  pub fn set_pixel(&self, x: u32, y: u32, color: u16) {
    if x > 127 || y > 31 {
      return
    }

    let index = (x + (y/8) * 128) as uint;
    if color == 0 {
      self.videobuf[index].set(
        self.videobuf[index].get() & !(1u8 << (y%8u32) as uint) as u8);
    } else {
      self.videobuf[index].set(
        self.videobuf[index].get() | (1 << ((y%8) as uint)));
    }
  }

  /// Prints a character to the display.
  pub fn character(&self, x: u32, y: u32, c: u8) {
    let width: u32 = 128;
    let height: u32 = 32;

    if (c < 31) || (c > 127) {
      return;
    }

    // read font parameter from start of array
    let offset = self.font[0];                    // bytes / char
    let hor = self.font[1];                       // get hor size of font
    let vert = self.font[2];                      // get vert size of font
    let bpl = self.font[3];                       // bytes per line

    let mut char_x: u32 = self.char_x.get();
    let mut char_y: u32 = self.char_y.get();

    if char_x + hor as u32 > width {
      char_x = 0;
      char_y = char_y + vert as u32;
      if char_y >= height - self.font[2] as u32 {
        char_y = 0;
      }
    }

    let start: uint = ((c - 32) as uint * offset as uint) + 4;
    let end: uint = start + offset as uint;
    let zeichen = self.font.slice(start, end);
    // zeichen = &self.font[]; // start of char bitmap
    let w = zeichen[0];                          // width of actual char
    // construct the char into the buffer
    for j in range(0, vert) {
      for i in range(0, hor) {
        let z: u8 =  zeichen[(bpl * i + ((j & 0xF8) >> 3)+1) as uint];
        let b: u8 = 1 << ((j & 0x07) as uint);
        if ( z & b ) == 0x00 {
          self.set_pixel(x+i as u32, y+j as u32, 0);
        } else {
          self.set_pixel(x+i as u32, y+j as u32, 1);
        }
      }
    }

    char_x += w as u32;

    self.char_x.set(char_x);
    self.char_y.set(char_y);
  }
}

impl<'a, S: Spi, T: Timer, P: Gpio> LCD for C12332<'a, S, T, P> {
  fn flush(&self) {
    let mut i: uint = 0;

    //page 0
    self.wr_cmd(0x00);      // set column low nibble 0
    self.wr_cmd(0x10);      // set column hi  nibble 0
    self.wr_cmd(0xB0);      // set page address  0
    self.dc.set_high();
    while i < 128 {
      self.wr_dat(self.videobuf[i].get());
      i += 1;
    }

    // page 1
    self.wr_cmd(0x00);      // set column low nibble 0
    self.wr_cmd(0x10);      // set column hi  nibble 0
    self.wr_cmd(0xB1);      // set page address  1
    self.dc.set_high();
    while i < 256 {
      self.wr_dat(self.videobuf[i].get());
      i += 1;
    }

    //page 2
    self.wr_cmd(0x00);      // set column low nibble 0
    self.wr_cmd(0x10);      // set column hi  nibble 0
    self.wr_cmd(0xB2);      // set page address  2
    self.dc.set_high();
    while i < 384 {
      self.wr_dat(self.videobuf[i].get());
      i += 1;
    }

    //page 3
    self.wr_cmd(0x00);      // set column low nibble 0
    self.wr_cmd(0x10);      // set column hi  nibble 0
    self.wr_cmd(0xB3);      // set page address  3
    self.dc.set_high();
    while i < 512 {
      self.wr_dat(self.videobuf[i].get());
      i += 1;
    }
  }

  fn clear(&self) {
    for i in range(0u, 512) {
      self.videobuf[i].set(0);
    }
  }

  fn pixel(&self, x: u32, y: u32, color: u16) {
    self.set_pixel(x, y, color);
  }
}

impl<'a, S: Spi, T: Timer, P: Gpio> CharIO for C12332<'a, S, T, P> {
  fn putc(&self, value: char) {
    let height: u32 = 32;
    if value == '\n' {
      self.char_x.set(0);
      self.char_y.set(self.char_y.get() + self.font[2] as u32);
      if self.char_y.get() >= height - self.font[2] as u32 {
          self.char_y.set(0);
      }
    } else {
      self.character(self.char_x.get(), self.char_y.get(), value as u8);
    }
  }
}
<commit_msg>Changed slice() to []<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*!
Driver for C12332 LCD.

C12332 is black&white LCD, the only supported color value is `1`. The LCD is
buffered in driver memory.

The driver uses SPI bus for output only, it never reads back from SPI, which
might be an issue for any other peripheral sharing the same SPI bus.
*/

use core::cell;
use core::slice::SliceExt;
use core::mem::zeroed;
use core::iter::range;

use super::font_small_7;
use super::LCD;
use drivers::chario::CharIO;
use hal::timer::Timer;
use hal::pin::Gpio;
use hal::spi::Spi;

/// C12332 driver.
pub struct C12332<'a, S:'a, T:'a, P:'a> {
  spi: &'a S,
  timer: &'a T,

  dc:    &'a P,
  cs:    &'a P,
  reset: &'a P,

  videobuf: [cell::Cell<u8>; 512],

  font: &'static [u8],
  char_x: cell::Cell<u32>,
  char_y: cell::Cell<u32>,
}

impl<'a, S: Spi, T: Timer, P: Gpio> C12332<'a, S, T, P> {
  /// Creates a new C12332 driver instance.
  pub fn new(spi: &'a S, timer: &'a T, dc: &'a P, cs: &'a P,
      reset: &'a P) -> C12332<'a, S, T, P> {
    let lcd = C12332 {
      spi:   spi,
      timer: timer,
      dc:    dc,
      cs:    cs,
      reset: reset,

      videobuf: unsafe { zeroed() },

      font: font_small_7::FONT,
      char_x: cell::Cell::new(0),
      char_y: cell::Cell::new(0),
    };

    lcd.configure();

    lcd
  }

  fn configure(&self) {
    self.dc.set_low();
    self.cs.set_high();
    self.reset.set_low();
    self.timer.wait_us(50);
    self.reset.set_high();
    self.timer.wait_ms(5);

    self.wr_cmd(0xAE);   //  display off
    self.wr_cmd(0xA2);   //  bias voltage

    self.wr_cmd(0xA0);
    self.wr_cmd(0xC8);   //  colum normal

    self.wr_cmd(0x22);   //  voltage resistor ratio
    self.wr_cmd(0x2F);   //  power on
    //self.wr_cmd(0xA4);   //  LCD display ram
    self.wr_cmd(0x40);   // start line = 0
    self.wr_cmd(0xAF);     // display ON

    self.wr_cmd(0x81);   //  set contrast
    self.wr_cmd(0x17);   //  set contrast

    self.wr_cmd(0xA6);     // display normal

    (self as &LCD).flush();
  }

  fn wr_cmd(&self, cmd: u8) {
    self.dc.set_low();
    self.cs.set_low();
    self.spi.write(cmd);
    self.cs.set_high();
  }

  fn wr_dat(&self, cmd: u8) {
    self.dc.set_high();
    self.cs.set_low();
    self.spi.write(cmd);
    self.cs.set_high();
  }

  /// Sets an individual pixel.
  pub fn set_pixel(&self, x: u32, y: u32, color: u16) {
    if x > 127 || y > 31 {
      return
    }

    let index = (x + (y/8) * 128) as uint;
    if color == 0 {
      self.videobuf[index].set(
        self.videobuf[index].get() & !(1u8 << (y%8u32) as uint) as u8);
    } else {
      self.videobuf[index].set(
        self.videobuf[index].get() | (1 << ((y%8) as uint)));
    }
  }

  /// Prints a character to the display.
  pub fn character(&self, x: u32, y: u32, c: u8) {
    let width: u32 = 128;
    let height: u32 = 32;

    if (c < 31) || (c > 127) {
      return;
    }

    // read font parameter from start of array
    let offset = self.font[0];                    // bytes / char
    let hor = self.font[1];                       // get hor size of font
    let vert = self.font[2];                      // get vert size of font
    let bpl = self.font[3];                       // bytes per line

    let mut char_x: u32 = self.char_x.get();
    let mut char_y: u32 = self.char_y.get();

    if char_x + hor as u32 > width {
      char_x = 0;
      char_y = char_y + vert as u32;
      if char_y >= height - self.font[2] as u32 {
        char_y = 0;
      }
    }

    let start: uint = ((c - 32) as uint * offset as uint) + 4;
    let end: uint = start + offset as uint;
    let zeichen = &self.font[start..end];
    // zeichen = &self.font[]; // start of char bitmap
    let w = zeichen[0];                          // width of actual char
    // construct the char into the buffer
    for j in range(0, vert) {
      for i in range(0, hor) {
        let z: u8 =  zeichen[(bpl * i + ((j & 0xF8) >> 3)+1) as uint];
        let b: u8 = 1 << ((j & 0x07) as uint);
        if ( z & b ) == 0x00 {
          self.set_pixel(x+i as u32, y+j as u32, 0);
        } else {
          self.set_pixel(x+i as u32, y+j as u32, 1);
        }
      }
    }

    char_x += w as u32;

    self.char_x.set(char_x);
    self.char_y.set(char_y);
  }
}

impl<'a, S: Spi, T: Timer, P: Gpio> LCD for C12332<'a, S, T, P> {
  fn flush(&self) {
    let mut i: uint = 0;

    //page 0
    self.wr_cmd(0x00);      // set column low nibble 0
    self.wr_cmd(0x10);      // set column hi  nibble 0
    self.wr_cmd(0xB0);      // set page address  0
    self.dc.set_high();
    while i < 128 {
      self.wr_dat(self.videobuf[i].get());
      i += 1;
    }

    // page 1
    self.wr_cmd(0x00);      // set column low nibble 0
    self.wr_cmd(0x10);      // set column hi  nibble 0
    self.wr_cmd(0xB1);      // set page address  1
    self.dc.set_high();
    while i < 256 {
      self.wr_dat(self.videobuf[i].get());
      i += 1;
    }

    //page 2
    self.wr_cmd(0x00);      // set column low nibble 0
    self.wr_cmd(0x10);      // set column hi  nibble 0
    self.wr_cmd(0xB2);      // set page address  2
    self.dc.set_high();
    while i < 384 {
      self.wr_dat(self.videobuf[i].get());
      i += 1;
    }

    //page 3
    self.wr_cmd(0x00);      // set column low nibble 0
    self.wr_cmd(0x10);      // set column hi  nibble 0
    self.wr_cmd(0xB3);      // set page address  3
    self.dc.set_high();
    while i < 512 {
      self.wr_dat(self.videobuf[i].get());
      i += 1;
    }
  }

  fn clear(&self) {
    for i in range(0u, 512) {
      self.videobuf[i].set(0);
    }
  }

  fn pixel(&self, x: u32, y: u32, color: u16) {
    self.set_pixel(x, y, color);
  }
}

impl<'a, S: Spi, T: Timer, P: Gpio> CharIO for C12332<'a, S, T, P> {
  fn putc(&self, value: char) {
    let height: u32 = 32;
    if value == '\n' {
      self.char_x.set(0);
      self.char_y.set(self.char_y.get() + self.font[2] as u32);
      if self.char_y.get() >= height - self.font[2] as u32 {
          self.char_y.set(0);
      }
    } else {
      self.character(self.char_x.get(), self.char_y.get(), value as u8);
    }
  }
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate serde_json;

use super::data_rw::{ReadPacketData, WritePacketData};
use super::{data_rw, json_data};
use std::ops::Deref;
use std::{convert, io};

/// * defines packet structure
/// * defines methods for each packet
/// * defines some enums for packets
/// * general packet to specific packet conversion
/// * specific packet to general packet conversion

#[derive(Debug)]
pub enum Error {
    DataRWError(data_rw::Error),
    JsonError(serde_json::Error),
}

impl_convert_for_error!(data_rw::Error, Error::DataRWError);
impl_convert_for_error!(serde_json::Error, Error::JsonError);

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum PacketType {
    HandShake,
    List,
    PingPong,
}

impl convert::From<PacketType> for i32 {
    fn from(packet: PacketType) -> i32 {
        use self::PacketType::*;

        match packet {
            HandShake => 0,
            List => 0,
            PingPong => 1,
        }
    }
}

#[derive(Debug)]
pub enum NextState {
    Status,
    Login,
}

impl convert::From<NextState> for i32 {
    fn from(state: NextState) -> i32 {
        use self::NextState::*;

        match state {
            Status => 1,
            Login => 2,
        }
    }
}

#[derive(Debug)]
pub struct GeneralPacket {
    pub packet_id: PacketType,
    pub body: io::Cursor<Vec<u8>>,
}

impl GeneralPacket {
    pub fn new(packet_id: PacketType) -> Self {
        Self {
            packet_id,
            body: io::Cursor::new(Vec::new()),
        }
    }

    pub fn with_body_vec(packet_id: PacketType, body_vec: Vec<u8>) -> Self {
        Self {
            packet_id,
            body: io::Cursor::new(body_vec),
        }
    }
}

pub trait ToGeneralPacket {
    fn to_general_packet(&self) -> Result<GeneralPacket, Error>;
}

pub trait FromGeneralPacket
where
    Self: Sized,
{
    fn from_general_packet(general_packet: &mut GeneralPacket) -> Result<Self, Error>;
}

#[derive(Debug)]
pub struct HandShakePacket {
    protocol_version: i32, // VarInt
    server_address: String,
    server_port: u16,
    next_state: i32, // VarInt
}

impl HandShakePacket {
    pub fn new(
        protocol_version: i32,
        server_address: &str,
        server_port: u16,
        next_state: NextState,
    ) -> Self {
        Self {
            protocol_version,
            server_address: server_address.to_owned(),
            server_port,
            next_state: next_state.into(),
        }
    }
}

impl ToGeneralPacket for HandShakePacket {
    fn to_general_packet(&self) -> Result<GeneralPacket, Error> {
        let mut packet = GeneralPacket::new(PacketType::HandShake);

        packet.body.write_varint(self.protocol_version)?;
        packet.body.write_string(self.server_address.deref())?;
        packet.body.write_unsigned_short(self.server_port)?;
        packet.body.write_varint(self.next_state)?;

        Ok(packet)
    }
}

pub struct ListRequestPacket;

impl ListRequestPacket {
    pub fn new() -> Self {
        ListRequestPacket::default()
    }
}

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

impl ToGeneralPacket for ListRequestPacket {
    fn to_general_packet(&self) -> Result<GeneralPacket, Error> {
        let packet = GeneralPacket::new(PacketType::List);
        Ok(packet)
    }
}

pub struct ListResponsePacket {
    pub status: json_data::status::Status,
}

impl ListResponsePacket {
    pub fn new(status: json_data::status::Status) -> Self {
        Self { status }
    }

    pub fn status(&self) -> &json_data::status::Status {
        &self.status
    }
}

impl FromGeneralPacket for ListResponsePacket {
    fn from_general_packet(general_packet: &mut GeneralPacket) -> Result<Self, Error> {
        let body_string = general_packet.body.read_string()?.content;
        let status: json_data::status::Status = serde_json::from_str(&body_string)?;
        Ok(ListResponsePacket::new(status))
    }
}

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

    #[test]
    fn handshake_to_general() {
        let from = HandShakePacket::new(335, "localhost", 25565, NextState::Status);
        let to = GeneralPacket::with_body_vec(
            PacketType::HandShake,
            vec![
                207, 2, 9, 108, 111, 99, 97, 108, 104, 111, 115, 116, 99, 221, 1,
            ],
        );

        let converted = from.to_general_packet().unwrap();

        assert_eq!(converted.packet_id, to.packet_id);
        assert_eq!(converted.body.get_ref(), to.body.get_ref());
    }

    #[test]
    fn list_response_from_general() {
        use self::json_data::chat::*;
        use self::json_data::status::*;
        use std::str::FromStr;

        let mut from = GeneralPacket::with_body_vec(PacketType::List, {
            let mut header: Vec<u8> = vec![0x8c, 0x0b];
            let mut body: Vec<u8> = Vec::from(
                r#"{"description":"A Minecraft Server","players":{"max":20,"online":0},"version":{"name":"1.7.10","protocol":5},"modinfo":{"type":"FML","modList":[{"modid":"mcp","version":"9.05"},{"modid":"FML","version":"7.10.99.99"},{"modid":"Forge","version":"10.13.4.1614"},{"modid":"clayiumtransformer","version":"0.4.1"},{"modid":"CodeChickenCore","version":"1.0.7.47"},{"modid":"NotEnoughItems","version":"1.0.5.120"},{"modid":"\u003cCoFH ASM\u003e","version":"000"},{"modid":"net.minecraft.scalar.cutall.mod_CutAllSMP","version":"2.5.0"},{"modid":"CoFHCore","version":"1.7.10R3.1.4"},{"modid":"BuildCraft|Core","version":"7.1.22"},{"modid":"BuildCraft|Transport","version":"7.1.22"},{"modid":"BuildCraft|Factory","version":"7.1.22"},{"modid":"BuildCraft|Silicon","version":"7.1.22"},{"modid":"BuildCraft|Robotics","version":"7.1.22"},{"modid":"BuildCraft|Energy","version":"7.1.22"},{"modid":"BuildCraft|Builders","version":"7.1.22"},{"modid":"ChickenChunks","version":"1.3.4.16"},{"modid":"IC2","version":"2.2.828-experimental"},{"modid":"ThermalFoundation","version":"1.7.10R1.2.6"},{"modid":"ThermalExpansion","version":"1.7.10R4.1.5"},{"modid":"clayium","version":"0.4.6.36.hotfix2"},{"modid":"exnihilo","version":"1.38-53"},{"modid":"exastris","version":"MC1.7.10-1.16-36"},{"modid":"inventorytweaks","version":"1.59-dev-152-cf6e263"},{"modid":"JABBA","version":"1.2.2"},{"modid":"ThermalDynamics","version":"1.7.10R1.2.1"}]}}"#,
            );

            header.append(&mut body);

            header
        });

        let to = ListResponsePacket::new(Status {
            version: Version {
                name: "1.7.10".to_owned(),
                protocol: 5u32,
            },
            description: Chat::from_str("A Minecraft Server").unwrap(),
            players: Players {
                max: 20,
                online: 0,
                sample: None,
            },
        });

        let converted = ListResponsePacket::from_general_packet(&mut from).unwrap();

        assert_eq!(converted.status.version.name, to.status.version.name);
    }
}
<commit_msg>fix: wrong recursive call<commit_after>extern crate serde;
extern crate serde_json;

use super::data_rw::{ReadPacketData, WritePacketData};
use super::{data_rw, json_data};
use std::ops::Deref;
use std::{convert, io};

/// * defines packet structure
/// * defines methods for each packet
/// * defines some enums for packets
/// * general packet to specific packet conversion
/// * specific packet to general packet conversion

#[derive(Debug)]
pub enum Error {
    DataRWError(data_rw::Error),
    JsonError(serde_json::Error),
}

impl_convert_for_error!(data_rw::Error, Error::DataRWError);
impl_convert_for_error!(serde_json::Error, Error::JsonError);

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum PacketType {
    HandShake,
    List,
    PingPong,
}

impl convert::From<PacketType> for i32 {
    fn from(packet: PacketType) -> i32 {
        use self::PacketType::*;

        match packet {
            HandShake => 0,
            List => 0,
            PingPong => 1,
        }
    }
}

#[derive(Debug)]
pub enum NextState {
    Status,
    Login,
}

impl convert::From<NextState> for i32 {
    fn from(state: NextState) -> i32 {
        use self::NextState::*;

        match state {
            Status => 1,
            Login => 2,
        }
    }
}

#[derive(Debug)]
pub struct GeneralPacket {
    pub packet_id: PacketType,
    pub body: io::Cursor<Vec<u8>>,
}

impl GeneralPacket {
    pub fn new(packet_id: PacketType) -> Self {
        Self {
            packet_id,
            body: io::Cursor::new(Vec::new()),
        }
    }

    pub fn with_body_vec(packet_id: PacketType, body_vec: Vec<u8>) -> Self {
        Self {
            packet_id,
            body: io::Cursor::new(body_vec),
        }
    }
}

pub trait ToGeneralPacket {
    fn to_general_packet(&self) -> Result<GeneralPacket, Error>;
}

pub trait FromGeneralPacket
where
    Self: Sized,
{
    fn from_general_packet(general_packet: &mut GeneralPacket) -> Result<Self, Error>;
}

#[derive(Debug)]
pub struct HandShakePacket {
    protocol_version: i32, // VarInt
    server_address: String,
    server_port: u16,
    next_state: i32, // VarInt
}

impl HandShakePacket {
    pub fn new(
        protocol_version: i32,
        server_address: &str,
        server_port: u16,
        next_state: NextState,
    ) -> Self {
        Self {
            protocol_version,
            server_address: server_address.to_owned(),
            server_port,
            next_state: next_state.into(),
        }
    }
}

impl ToGeneralPacket for HandShakePacket {
    fn to_general_packet(&self) -> Result<GeneralPacket, Error> {
        let mut packet = GeneralPacket::new(PacketType::HandShake);

        packet.body.write_varint(self.protocol_version)?;
        packet.body.write_string(self.server_address.deref())?;
        packet.body.write_unsigned_short(self.server_port)?;
        packet.body.write_varint(self.next_state)?;

        Ok(packet)
    }
}

#[derive(Default)]
pub struct ListRequestPacket;

impl ListRequestPacket {
    pub fn new() -> Self {
        ListRequestPacket::default()
    }
}

impl ToGeneralPacket for ListRequestPacket {
    fn to_general_packet(&self) -> Result<GeneralPacket, Error> {
        let packet = GeneralPacket::new(PacketType::List);
        Ok(packet)
    }
}

pub struct ListResponsePacket {
    pub status: json_data::status::Status,
}

impl ListResponsePacket {
    pub fn new(status: json_data::status::Status) -> Self {
        Self { status }
    }

    pub fn status(&self) -> &json_data::status::Status {
        &self.status
    }
}

impl FromGeneralPacket for ListResponsePacket {
    fn from_general_packet(general_packet: &mut GeneralPacket) -> Result<Self, Error> {
        let body_string = general_packet.body.read_string()?.content;
        let status: json_data::status::Status = serde_json::from_str(&body_string)?;
        Ok(ListResponsePacket::new(status))
    }
}

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

    #[test]
    fn handshake_to_general() {
        let from = HandShakePacket::new(335, "localhost", 25565, NextState::Status);
        let to = GeneralPacket::with_body_vec(
            PacketType::HandShake,
            vec![
                207, 2, 9, 108, 111, 99, 97, 108, 104, 111, 115, 116, 99, 221, 1,
            ],
        );

        let converted = from.to_general_packet().unwrap();

        assert_eq!(converted.packet_id, to.packet_id);
        assert_eq!(converted.body.get_ref(), to.body.get_ref());
    }

    #[test]
    fn list_response_from_general() {
        use self::json_data::chat::*;
        use self::json_data::status::*;
        use std::str::FromStr;

        let mut from = GeneralPacket::with_body_vec(PacketType::List, {
            let mut header: Vec<u8> = vec![0x8c, 0x0b];
            let mut body: Vec<u8> = Vec::from(
                r#"{"description":"A Minecraft Server","players":{"max":20,"online":0},"version":{"name":"1.7.10","protocol":5},"modinfo":{"type":"FML","modList":[{"modid":"mcp","version":"9.05"},{"modid":"FML","version":"7.10.99.99"},{"modid":"Forge","version":"10.13.4.1614"},{"modid":"clayiumtransformer","version":"0.4.1"},{"modid":"CodeChickenCore","version":"1.0.7.47"},{"modid":"NotEnoughItems","version":"1.0.5.120"},{"modid":"\u003cCoFH ASM\u003e","version":"000"},{"modid":"net.minecraft.scalar.cutall.mod_CutAllSMP","version":"2.5.0"},{"modid":"CoFHCore","version":"1.7.10R3.1.4"},{"modid":"BuildCraft|Core","version":"7.1.22"},{"modid":"BuildCraft|Transport","version":"7.1.22"},{"modid":"BuildCraft|Factory","version":"7.1.22"},{"modid":"BuildCraft|Silicon","version":"7.1.22"},{"modid":"BuildCraft|Robotics","version":"7.1.22"},{"modid":"BuildCraft|Energy","version":"7.1.22"},{"modid":"BuildCraft|Builders","version":"7.1.22"},{"modid":"ChickenChunks","version":"1.3.4.16"},{"modid":"IC2","version":"2.2.828-experimental"},{"modid":"ThermalFoundation","version":"1.7.10R1.2.6"},{"modid":"ThermalExpansion","version":"1.7.10R4.1.5"},{"modid":"clayium","version":"0.4.6.36.hotfix2"},{"modid":"exnihilo","version":"1.38-53"},{"modid":"exastris","version":"MC1.7.10-1.16-36"},{"modid":"inventorytweaks","version":"1.59-dev-152-cf6e263"},{"modid":"JABBA","version":"1.2.2"},{"modid":"ThermalDynamics","version":"1.7.10R1.2.1"}]}}"#,
            );

            header.append(&mut body);

            header
        });

        let to = ListResponsePacket::new(Status {
            version: Version {
                name: "1.7.10".to_owned(),
                protocol: 5u32,
            },
            description: Chat::from_str("A Minecraft Server").unwrap(),
            players: Players {
                max: 20,
                online: 0,
                sample: None,
            },
        });

        let converted = ListResponsePacket::from_general_packet(&mut from).unwrap();

        assert_eq!(converted.status.version.name, to.status.version.name);
    }
}
<|endoftext|>


<commit_before>extern crate bindgen;
extern crate pkg_config;

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e{
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

const LIBMODBUS_DIR: &'static str = "libmodbus";

fn main() {
    let dst = env::var("OUT_DIR").unwrap();
    let target = env::var("TARGET").unwrap();
    let host = env::var("HOST").unwrap();

    let build_dir = Path::new(LIBMODBUS_DIR);
    let prefix    = Path::new(&dst).join("libmodbus-root");
    let include   = Path::new(&prefix).join("include")
                                      .join("modbus");

    // if `pkg-config` is present and the libmodbus headers are found
    // we use `pkg-config` to find the include_path and call bindgen with it.
    //
    if let Ok(library) = pkg_config::find_library("libmodbus") {
        if let Some(include) = library.include_paths.get(0) {
            run_bindgen(&include);
        }

        return
    }

    // pkg-config is not found. We build libmodbus from source (source are in a git submodule)
    // and run bindgen with that folder as include path set.
    //

    // If autogen.sh is not present, initalize git submodules
    if !Path::new("libmodbus/autogen.sh").exists() {
        run_command("", Command::new("git").args(&["submodule", "update", "--init"]));
    }

    let _ = fs::remove_dir_all(env::var("OUT_DIR").unwrap());
    t!(fs::create_dir_all(env::var("OUT_DIR").unwrap()));

    // Generate configure, run configure, make, make install
    run_command("Generating configure",
        Command::new("autoreconf")
            .arg("--install")
            .arg("--symlink")
            .arg("--force")
            .current_dir(&build_dir));

    run_command("Configuring libmodbus",
        Command::new("./configure")
            .arg("--prefix")
            .arg(prefix)
            .arg(format!("--target={}", target))
            .arg(format!("--host={}", host))
            .current_dir(&build_dir));

    run_command("Building libmodbus",
        Command::new("make")
            .arg("install")
            .current_dir(&build_dir));

    println!("cargo:rustc-link-lib=modbus");
    println!("cargo:rustc-link-search=native={}/libmodbus-root/lib", dst);

    run_bindgen(&include);
}

fn run_bindgen(include: &PathBuf) {
    let include_path = format!("-I{}", include.display());

    // The bindgen::Builder is the main entry point
    // to bindgen, and lets you build up options for
    // the resulting bindings.
    let bindings = bindgen::Builder::default()
        // Do not generate unstable Rust code that
        // requires a nightly rustc and enabling
        // unstable features.
        .no_unstable_rust()
        // The input header we would like to generate
        // bindings for.
        .header("wrapper.h")
        .clang_arg(include_path)
        // Finish the builder and generate the bindings.
        .generate()
        // Unwrap the Result and panic on failure.
        .expect("Unable to generate bindings");

    // Write the bindings to the $OUT_DIR/bindings.rs file.
    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");
}

// Helper which run a given command, and check it's success
fn run_command(which: &'static str, cmd: &mut Command) {
    assert!(cmd.status().expect(which).success(), which);
}
<commit_msg>Test som more configure parameter for building under yocto<commit_after>extern crate bindgen;
extern crate pkg_config;
extern crate gcc;

use std::env;
use std::ffi::OsString;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;

// stolen from: https://github.com/alexcrichton/backtrace-rs/blob/master/backtrace-sys/build.rs
macro_rules! t {
    ($e:expr) => (match $e{
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

// stolen from: https://github.com/alexcrichton/backtrace-rs/blob/master/backtrace-sys/build.rs
fn try_tool(compiler: &gcc::Tool, cc: &str, compiler_suffix: &str, tool_suffix: &str)
            -> Option<PathBuf> {
    if !cc.ends_with(compiler_suffix) {
        return None
    }
    let cc = cc.replace(compiler_suffix, tool_suffix);
    let candidate = compiler.path().parent().unwrap().join(cc);
    if Command::new(&candidate).output().is_ok() {
        Some(candidate)
    } else {
        None
    }
}
// stolen from: https://github.com/alexcrichton/backtrace-rs/blob/master/backtrace-sys/build.rs, too
fn find_tool(compiler: &gcc::Tool, cc: &str, tool: &str) -> PathBuf {
    // Allow overrides via env var
    if let Some(s) = env::var_os(tool.to_uppercase()) {
        return s.into()
    }
    let tool_suffix = format!("-{}", tool);
    try_tool(compiler, cc, "-gcc", &tool_suffix)
        .or_else(|| try_tool(compiler, cc, "-clang", &tool_suffix))
        .or_else(|| try_tool(compiler, cc, "-cc", &tool_suffix))
        .unwrap_or_else(|| PathBuf::from(tool))
}

const LIBMODBUS_DIR: &'static str = "libmodbus";

fn main() {
    let dst = env::var("OUT_DIR").unwrap();
    let target = env::var("TARGET").unwrap();
    let host = env::var("HOST").unwrap();

    let build_dir = Path::new(LIBMODBUS_DIR);
    let prefix    = Path::new(&dst).join("libmodbus-root");
    let include   = Path::new(&prefix).join("include")
                                      .join("modbus");

    // if `pkg-config` is present and the libmodbus headers are found
    // we use `pkg-config` to find the include_path and call bindgen with it.
    //
    if let Ok(library) = pkg_config::find_library("libmodbus") {
        if let Some(include) = library.include_paths.get(0) {
            run_bindgen(&include);
        }

        return
    }

    // pkg-config is not found. We build libmodbus from source (source are in a git submodule)
    // and run bindgen with that folder as include path set.
    //

    // If autogen.sh is not present, initalize git submodules
    if !Path::new("libmodbus/autogen.sh").exists() {
        run_command("", Command::new("git").args(&["submodule", "update", "--init"]));
    }

    let _ = fs::remove_dir_all(env::var("OUT_DIR").unwrap());
    t!(fs::create_dir_all(env::var("OUT_DIR").unwrap()));

    let cfg = gcc::Config::new();
    let compiler = cfg.get_compiler();
    let cc = compiler.path().file_name().unwrap().to_str().unwrap();
    let mut flags = OsString::new();
    for (i, flag) in compiler.args().iter().enumerate() {
        if i > 0 {
            flags.push(" ");
        }
        flags.push(flag);
    }

    // Generate configure, run configure, make, make install
    run_command("Generating configure",
        Command::new("autoreconf")
            .arg("--install")
            .arg("--symlink")
            .arg("--force")
            .current_dir(&build_dir));

    run_command("Configuring libmodbus",
        Command::new("./configure")
            .arg("--prefix")
            .arg(&prefix)
            .env("CC", compiler.path())
            .env("CFLAGS", flags)
            .arg("--with-pic")
            .arg("--disable-multilib")
            .arg("--disable-shared")
            .arg("--disable-host-shared")
            .arg(format!("--target={}", target))
            .arg(format!("--host={}", host))
            .current_dir(&build_dir));

    run_command("Building libmodbus",
        Command::new("make")
            .arg("install")
            .current_dir(&build_dir));

    println!("cargo:rustc-link-lib=modbus");
    println!("cargo:rustc-link-search=native={}/libmodbus-root/lib", dst);

    run_bindgen(&include);
}

fn run_bindgen(include: &PathBuf) {
    let include_path = format!("-I{}", include.display());

    // The bindgen::Builder is the main entry point
    // to bindgen, and lets you build up options for
    // the resulting bindings.
    let bindings = bindgen::Builder::default()
        // Do not generate unstable Rust code that
        // requires a nightly rustc and enabling
        // unstable features.
        .no_unstable_rust()
        // The input header we would like to generate
        // bindings for.
        .header("wrapper.h")
        .clang_arg(include_path)
        // Finish the builder and generate the bindings.
        .generate()
        // Unwrap the Result and panic on failure.
        .expect("Unable to generate bindings");

    // Write the bindings to the $OUT_DIR/bindings.rs file.
    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");
}

// Helper which run a given command, and check it's success
fn run_command(which: &'static str, cmd: &mut Command) {
    assert!(cmd.status().expect(which).success(), which);
}
<|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" />
<% from data import Method %>

// CSS Basic User Interface Module Level 1
// https://drafts.csswg.org/css-ui-3/
<% data.new_style_struct("UI", inherited=False, gecko_name="UIReset") %>

// TODO spec says that UAs should not support this
// we should probably remove from gecko (https://bugzilla.mozilla.org/show_bug.cgi?id=1328331)
${helpers.single_keyword("ime-mode", "auto normal active disabled inactive",
                         products="gecko", gecko_ffi_name="mIMEMode",
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-ui/#input-method-editor")}

${helpers.single_keyword("-moz-user-select", "auto text none all element elements" +
                            " toggle tri-state -moz-all -moz-text",
                         products="gecko",
                         alias="-webkit-user-select",
                         gecko_ffi_name="mUserSelect",
                         gecko_enum_prefix="StyleUserSelect",
                         gecko_inexhaustive=True,
                         gecko_strip_moz_prefix=False,
                         aliases="-moz-none=none",
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-ui-4/#propdef-user-select")}

${helpers.single_keyword("-moz-window-dragging", "default drag no-drag", products="gecko",
                         gecko_ffi_name="mWindowDragging",
                         gecko_enum_prefix="StyleWindowDragging",
                         gecko_inexhaustive=True,
                         animation_value_type="discrete",
                         spec="None (Nonstandard Firefox-only property)")}

${helpers.single_keyword("-moz-window-shadow", "none default menu tooltip sheet", products="gecko",
                         gecko_ffi_name="mWindowShadow",
                         gecko_constant_prefix="NS_STYLE_WINDOW_SHADOW",
                         gecko_inexhaustive=True,
                         animation_value_type="discrete",
                         internal=True,
                         spec="None (Nonstandard internal property)")}

<%helpers:longhand name="-moz-force-broken-image-icon"
                   products="gecko"
                   animation_value_type="discrete"
                   spec="None (Nonstandard Firefox-only property)">
    use std::fmt;
    use style_traits::ToCss;
    use values::computed::ComputedValueAsSpecified;

    pub mod computed_value {
        #[derive(Clone, Copy, Debug, PartialEq)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        pub struct T(pub bool);
    }

    pub use self::computed_value::T as SpecifiedValue;

    impl ToCss for computed_value::T {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            dest.write_str(if self.0 { "1" } else { "0" })
        }
    }

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        computed_value::T(false)
    }

    #[inline]
    pub fn get_initial_specified_value() -> SpecifiedValue {
        computed_value::T(false)
    }

    impl ComputedValueAsSpecified for SpecifiedValue {}

    pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                         -> Result<SpecifiedValue, ParseError<'i>> {
        match input.expect_integer()? {
            0 => Ok(computed_value::T(false)),
            1 => Ok(computed_value::T(true)),
            _ => Err(StyleParseError::UnspecifiedError.into()),
        }
    }

    impl From<u8> for SpecifiedValue {
        fn from(bits: u8) -> SpecifiedValue {
            SpecifiedValue(bits == 1)
        }
    }

    impl From<SpecifiedValue> for u8 {
        fn from(v: SpecifiedValue) -> u8 {
            match v.0 {
                true => 1u8,
                false => 0u8,
            }
        }
    }
</%helpers:longhand>
<commit_msg>Do not use CVAS for the -moz-force-broken-image-icon property<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" />
<% from data import Method %>

// CSS Basic User Interface Module Level 1
// https://drafts.csswg.org/css-ui-3/
<% data.new_style_struct("UI", inherited=False, gecko_name="UIReset") %>

// TODO spec says that UAs should not support this
// we should probably remove from gecko (https://bugzilla.mozilla.org/show_bug.cgi?id=1328331)
${helpers.single_keyword("ime-mode", "auto normal active disabled inactive",
                         products="gecko", gecko_ffi_name="mIMEMode",
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-ui/#input-method-editor")}

${helpers.single_keyword("-moz-user-select", "auto text none all element elements" +
                            " toggle tri-state -moz-all -moz-text",
                         products="gecko",
                         alias="-webkit-user-select",
                         gecko_ffi_name="mUserSelect",
                         gecko_enum_prefix="StyleUserSelect",
                         gecko_inexhaustive=True,
                         gecko_strip_moz_prefix=False,
                         aliases="-moz-none=none",
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-ui-4/#propdef-user-select")}

${helpers.single_keyword("-moz-window-dragging", "default drag no-drag", products="gecko",
                         gecko_ffi_name="mWindowDragging",
                         gecko_enum_prefix="StyleWindowDragging",
                         gecko_inexhaustive=True,
                         animation_value_type="discrete",
                         spec="None (Nonstandard Firefox-only property)")}

${helpers.single_keyword("-moz-window-shadow", "none default menu tooltip sheet", products="gecko",
                         gecko_ffi_name="mWindowShadow",
                         gecko_constant_prefix="NS_STYLE_WINDOW_SHADOW",
                         gecko_inexhaustive=True,
                         animation_value_type="discrete",
                         internal=True,
                         spec="None (Nonstandard internal property)")}

<%helpers:longhand name="-moz-force-broken-image-icon"
                   products="gecko"
                   animation_value_type="discrete"
                   spec="None (Nonstandard Firefox-only property)">
    use std::fmt;
    use style_traits::ToCss;

    pub mod computed_value {
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        #[derive(Clone, Copy, Debug, PartialEq, ToComputedValue)]
        pub struct T(pub bool);
    }

    pub use self::computed_value::T as SpecifiedValue;

    impl ToCss for computed_value::T {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            dest.write_str(if self.0 { "1" } else { "0" })
        }
    }

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        computed_value::T(false)
    }

    #[inline]
    pub fn get_initial_specified_value() -> SpecifiedValue {
        computed_value::T(false)
    }

    pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                         -> Result<SpecifiedValue, ParseError<'i>> {
        match input.expect_integer()? {
            0 => Ok(computed_value::T(false)),
            1 => Ok(computed_value::T(true)),
            _ => Err(StyleParseError::UnspecifiedError.into()),
        }
    }

    impl From<u8> for SpecifiedValue {
        fn from(bits: u8) -> SpecifiedValue {
            SpecifiedValue(bits == 1)
        }
    }

    impl From<SpecifiedValue> for u8 {
        fn from(v: SpecifiedValue) -> u8 {
            match v.0 {
                true => 1u8,
                false => 0u8,
            }
        }
    }
</%helpers:longhand>
<|endoftext|>


<commit_before>extern crate wm_daemons;
use wm_daemons::config::{load_config, load_config_path};
use wm_daemons::dbus_listen::{CallbackMap, DBusInfo, match_signal};
use wm_daemons::exec::{CommandLine, read_command_line_from_config, run_command_line};

#[macro_use]
extern crate clap;
use clap::{Arg, App};

extern crate dbus;
use self::dbus::{Connection, BusType, Message};

use std::env::var;
use std::error::Error;
use std::path::Path;

struct Context {
    on_lock: Option<CommandLine>,
    on_unlock: Option<CommandLine>,
}

fn run_program(action: &str, cmd_line: &Option<CommandLine>) -> () {
    cmd_line.as_ref().map(|ref cmd| {
        let _ = run_command_line(&cmd).map_err(|err| {
                println!("failed to handle '{}' action: {}", action, err);
            });
    });
}

fn handle_signal(ctx: Context, info: &Message) -> Context {
    let (_, _, _, member) = info.headers();

    member.map(|member_name| {
        if member_name == "Lock" {
            run_program("lock", &ctx.on_lock);
        } else if member_name == "Unlock" {
            run_program("unlock", &ctx.on_unlock);
        }
    });

    ctx
}

fn try_main() -> Result<(), Box<Error>> {
    let matches = App::new("wm-session-agent")
        .version(&crate_version!()[..])
        .author("Ben Boeckel <mathstuf@gmail.com>")
        .about("Listens for logind's Lock and Unlock signals")
        .arg(Arg::with_name("CONFIG")
                .short("c")
                .long("config")
                .help("Path to the configuration file")
                .takes_value(true))
        .arg(Arg::with_name("SESSION")
                .short("s")
                .long("session")
                .help("Session ID to listen on")
                .takes_value(true))
        .get_matches();

    let conf = try!(match matches.value_of("CONFIG") {
        Some(path) => load_config_path(Path::new(path)),
        None => load_config("wm-session-agent", "config"),
    });
    let ctx = Context {
        on_lock: read_command_line_from_config(&conf, "actions.lock"),
        on_unlock: read_command_line_from_config(&conf, "actions.unlock"),
    };

    let sid = match matches.value_of("SESSION") {
        Some(sid) => sid.to_string(),
        None => match var("XDG_SESSION_ID") {
            Ok(sid) => sid,
            Err(err) => {
                println!("No session ID given or available: {}", err);
                return Err(Box::new(err));
            },
        },
    };
    let spath = format!("/org/freedesktop/login1/session/_{}", sid);

    let conn = try!(Connection::get_private(BusType::System));

    let cbs: CallbackMap<Context> = vec![
        (DBusInfo {
            path: None,
            object: None,
            member: Some("Lock".to_string()),
        }, handle_signal),
        (DBusInfo {
            path: None,
            object: None,
            member: Some("Unlock".to_string()),
        }, handle_signal),
    ];

    let match_str = format!("type='signal',interface='org.freedesktop.login1.Session',path='{}'", spath);
    try!(conn.add_match(&match_str[..]));

    conn.iter(100).fold(ctx, |inner_ctx, item| {
        match_signal(inner_ctx, &cbs, item)
    });

    Ok(())
}

fn main() -> () {
    if let Err(err) = try_main() {
        panic!("{}", err.description());
    }
}
<commit_msg>wm-session-agent: use a better environment name<commit_after>extern crate wm_daemons;
use wm_daemons::config::{load_config, load_config_path};
use wm_daemons::dbus_listen::{CallbackMap, DBusInfo, match_signal};
use wm_daemons::exec::{CommandLine, read_command_line_from_config, run_command_line};

#[macro_use]
extern crate clap;
use clap::{Arg, App};

extern crate dbus;
use self::dbus::{Connection, BusType, Message};

use std::env::var;
use std::error::Error;
use std::path::Path;

struct Context {
    on_lock: Option<CommandLine>,
    on_unlock: Option<CommandLine>,
}

fn run_program(action: &str, cmd_line: &Option<CommandLine>) -> () {
    cmd_line.as_ref().map(|ref cmd| {
        let _ = run_command_line(&cmd).map_err(|err| {
                println!("failed to handle '{}' action: {}", action, err);
            });
    });
}

fn handle_signal(ctx: Context, info: &Message) -> Context {
    let (_, _, _, member) = info.headers();

    member.map(|member_name| {
        if member_name == "Lock" {
            run_program("lock", &ctx.on_lock);
        } else if member_name == "Unlock" {
            run_program("unlock", &ctx.on_unlock);
        }
    });

    ctx
}

fn try_main() -> Result<(), Box<Error>> {
    let matches = App::new("wm-session-agent")
        .version(&crate_version!()[..])
        .author("Ben Boeckel <mathstuf@gmail.com>")
        .about("Listens for logind's Lock and Unlock signals")
        .arg(Arg::with_name("CONFIG")
                .short("c")
                .long("config")
                .help("Path to the configuration file")
                .takes_value(true))
        .arg(Arg::with_name("SESSION")
                .short("s")
                .long("session")
                .help("Session ID to listen on")
                .takes_value(true))
        .get_matches();

    let conf = try!(match matches.value_of("CONFIG") {
        Some(path) => load_config_path(Path::new(path)),
        None => load_config("wm-session-agent", "config"),
    });
    let ctx = Context {
        on_lock: read_command_line_from_config(&conf, "actions.lock"),
        on_unlock: read_command_line_from_config(&conf, "actions.unlock"),
    };

    let sid = match matches.value_of("SESSION") {
        Some(sid) => sid.to_string(),
        None => match var("LOGIND_SESSION_ID") {
            Ok(sid) => sid,
            Err(err) => {
                println!("No session ID given or available: {}", err);
                return Err(Box::new(err));
            },
        },
    };
    let spath = format!("/org/freedesktop/login1/session/{}", sid);

    let conn = try!(Connection::get_private(BusType::System));

    let cbs: CallbackMap<Context> = vec![
        (DBusInfo {
            path: None,
            object: None,
            member: Some("Lock".to_string()),
        }, handle_signal),
        (DBusInfo {
            path: None,
            object: None,
            member: Some("Unlock".to_string()),
        }, handle_signal),
    ];

    let match_str = format!("type='signal',interface='org.freedesktop.login1.Session',path='{}'", spath);
    try!(conn.add_match(&match_str[..]));

    conn.iter(100).fold(ctx, |inner_ctx, item| {
        match_signal(inner_ctx, &cbs, item)
    });

    Ok(())
}

fn main() -> () {
    if let Err(err) = try_main() {
        panic!("{}", err.description());
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::iter;
use std::f64;
use std::sync::{Arc, RwLock};

use adivon::bag::Bag;
use adivon::queue::Queue;

/// Capacitated edge with a flow in a flow network.
pub struct FlowEdge {
    v: usize,                   // from
    w: usize,                   // to
    capacity: f64,
    flow: f64
}

impl FlowEdge {
    pub fn new(v: usize, w: usize, capacity: f64) -> FlowEdge {
        assert!(capacity >= 0.0, "edge capacity must be non-negative");
        FlowEdge {
            v: v,
            w: w,
            capacity: capacity,
            flow: 0.0
        }
    }

    pub fn new_with_flow(v: usize, w: usize, capacity: f64, flow: f64) -> FlowEdge {
        assert!(capacity >= 0.0, "edge capacity must be non-negative");
        assert!(flow <= capacity, "flow exceeds capacity");
        assert!(flow >= 0.0, "flow must be non-negative");
        FlowEdge {
            v: v,
            w: w,
            capacity: capacity,
            flow: flow
        }
    }

    pub fn from(&self) -> usize {
        self.v
    }

    pub fn to(&self) -> usize {
        self.w
    }

    pub fn capacity(&self) -> f64 {
        self.capacity
    }

    pub fn flow(&self) -> f64 {
        self.flow
    }

    pub fn other(&self, vertex: usize) -> usize {
        if vertex == self.v {
            self.w
        } else if vertex == self.w {
            self.v
        } else {
            panic!("illegal endpoint")
        }
    }

    pub fn residual_capacity_to(&self, vertex: usize) -> f64 {
        if vertex == self.v {
            self.flow
        } else if vertex == self.w {
            self.capacity - self.flow
        } else {
            panic!("illegal endpoint")
        }
    }

    pub fn add_residual_flow_to(&mut self, vertex: usize, delta: f64) {
        assert!(!delta.is_nan(), "change in flow = NaN");
        if vertex == self.v {
            self.flow -= delta;
        } else if vertex == self.w {
            self.flow += delta;
        } else {
            panic!("illegal endpoint")
        }
        assert!(self.flow >= 0.0 && self.flow <= self.capacity)
    }
}

impl fmt::Debug for FlowEdge {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} -> {} {}/{}", self.v, self.w, self.flow, self.capacity)
    }
}

#[test]
fn test_flow_edge() {
    let e = FlowEdge::new(12, 23, 3.14);
    assert_eq!("12 -> 23 0/3.14", format!("{:?}", e));
}

/// A capacitated flow network, implemented using adjacency lists.
pub struct FlowNetwork {
    v: usize,
    e: usize,
    adj: Vec<Bag<Arc<RwLock<FlowEdge>>>>
}

impl FlowNetwork {
    pub fn new(v: usize) -> FlowNetwork {
        FlowNetwork {
            v: v,
            e: 0,
            adj: iter::repeat(Bag::new()).take(v).collect()
        }
    }

    pub fn v(&self) -> usize {
        self.v
    }

    pub fn e(&self) -> usize {
        self.e
    }

    fn validate_vertex(&self, v: usize) {
        assert!(v < self.v())
    }

    pub fn add_edge(&mut self, e: FlowEdge) {
        let v = e.from();
        let w = e.to();
        self.validate_vertex(v);
        self.validate_vertex(w);
        let edge = Arc::new(RwLock::new(e));
        self.adj[v].add(edge.clone());
        self.adj[w].add(edge);
        self.e += 1;
    }

    pub fn adj<'r>(&'r self, v: usize) -> Vec<Arc<RwLock<FlowEdge>>> {
        self.validate_vertex(v);
        self.adj[v].iter().map(|e| e.clone()).collect()
    }

    pub fn edges<'r>(&'r self) -> Vec<Arc<RwLock<FlowEdge>>> {
        self.adj.iter()
            .flat_map(|adj| {
                adj.iter()
                    .map(|e| e.clone())
                    .collect::<Vec<Arc<RwLock<FlowEdge>>>>()
                    .into_iter()
            })
            .collect()
    }

    pub fn to_dot(&self) -> String {
        let mut dot = String::new();

        dot.push_str("digraph G {\n");
        for i in 0 .. self.v {
            dot.push_str(&format!("  {};\n", i));
        }

        for v in 0 .. self.v() {
            for e in self.adj(v) {
                let e = e.read().unwrap();
                if v == e.from() {
                    let w = e.to();
                    dot.push_str(&format!("  {} -> {} [ label=\"{}/{}\" ];\n",
                                          v, w, e.flow, e.capacity));
                }
            }
        }
        dot.push_str("}\n");
        dot
    }
}

/// Ford-Fulkerson algorithm for computing a max flow and
/// a min cut using shortest augmenting path rule.
pub struct FordFulkerson<'g> {
    graph: &'g FlowNetwork,
    marked: Vec<bool>,
    edge_to: Vec<Option<Arc<RwLock<FlowEdge>>>>,
    value: f64
}

impl<'g> FordFulkerson<'g> {
    fn new<'a>(graph: &'a FlowNetwork, s: usize, t: usize) -> FordFulkerson<'a> {
        graph.validate_vertex(s);
        graph.validate_vertex(t);

        let n = graph.v();
        let mut ret = FordFulkerson {
            graph: graph,
            marked: iter::repeat(false).take(n).collect(),
            edge_to: iter::repeat(None).take(n).collect(),
            value: 0.0
        };
        ret.ford_fulkerson(s, t);
        ret
    }

    fn ford_fulkerson(&mut self, s: usize, t: usize) {
        if !self.is_feasible(s, t) {
            panic!("initial flow is infeasible");
        }

        self.value = self.excess(t);
        while self.has_augmenting_path(s, t) {
            let mut bottle = f64::INFINITY;
            let mut v = t;
            while v != s {
                let ee = self.edge_to[v].as_ref().unwrap().clone();
                bottle = bottle.min(ee.write().unwrap().residual_capacity_to(v));
                v = ee.read().unwrap().other(v);
            }

            // augment flow
            let mut v = t;
            while v != s {
                let ee = self.edge_to[v].as_ref().unwrap().clone();
                ee.write().unwrap().add_residual_flow_to(v, bottle);
                v = ee.read().unwrap().other(v);
            }

            self.value += bottle;
        }
    }

    pub fn value(&self) -> f64 {
        self.value
    }

    // is v in the s side of the min s-t cut?
    pub fn in_cut(&self, v: usize) -> bool {
        self.graph.validate_vertex(v);
        self.marked[v]
    }

    // is there an augmenting path?
    fn has_augmenting_path(&mut self, s: usize, t: usize) -> bool {
        self.edge_to = iter::repeat(None).take(self.graph.v()).collect();
        self.marked = iter::repeat(false).take(self.graph.v()).collect();

        let mut queue = Queue::<usize>::new();
        queue.enqueue(s);
        self.marked[s] = true;
        while !queue.is_empty() && !self.marked[t] {
            let v = queue.dequeue().unwrap();

            for ee in self.graph.adj(v) {
                let e = ee.read().unwrap();
                let w = e.other(v);

                // if residual capacity from v to w
                if e.residual_capacity_to(w) > 0.0 {
                    if !self.marked[w] {
                        self.edge_to[w] = Some(ee.clone());
                        self.marked[w] = true;
                        queue.enqueue(w);
                    }
                }
            }
        }
        self.marked[t]
    }

    // return excess flow at vertex v
    fn excess(&self, v: usize) -> f64 {
        let mut excess = 0f64;
        for e in self.graph.adj(v) {
            let e = e.read().unwrap();
            if v == e.from() {
                excess -= e.flow();
            } else {
                excess += e.flow();
            }
        }
        excess
    }

    fn is_feasible(&self, s: usize, t: usize) -> bool {
        const EPSILON: f64 = 1e-11;

        // check that capacity constraints are satisfied
        for v in 0 .. self.graph.v() {
            for e in self.graph.adj(v) {
                let e = e.read().unwrap();
                if e.flow() < -EPSILON || e.flow() > e.capacity() + EPSILON {
                    panic!("edge does not satisfy capacity constraints");
                    // return false;
                }
            }
        }

        // check that net flow into a vertex equals zero, except at source and sink
        if (self.value + self.excess(s)).abs() > EPSILON {
            panic!("Excess at source = {}", self.excess(s));
            // return false;
        }

        for v in 0 .. self.graph.v() {
            if v == s || v == t {
                continue;
            } else {
                if self.excess(v).abs() > EPSILON {
                    panic!("net flow out of {:?} doesn't equal zero", v);
                    // return false;
                }
            }
        }
        return true;
    }
}

impl FlowNetwork {
    pub fn ford_fulkerson<'a>(&'a mut self, s: usize, t: usize) -> FordFulkerson<'a> {
        assert!(s != t, "source equal to sink");
        FordFulkerson::new(self, s, t)
    }
}

#[test]
fn test_flow_network() {
    let mut g = FlowNetwork::new(6);

    g.add_edge(FlowEdge::new(0, 1, 2.0));
    g.add_edge(FlowEdge::new(0, 2, 3.0));
    g.add_edge(FlowEdge::new(1, 3, 3.0));
    g.add_edge(FlowEdge::new(1, 4, 1.0));
    g.add_edge(FlowEdge::new(2, 3, 1.0));
    g.add_edge(FlowEdge::new(2, 4, 1.0));
    g.add_edge(FlowEdge::new(3, 5, 2.0));
    g.add_edge(FlowEdge::new(4, 3, 3.0));

    // println!("=> \n{}", g.to_dot());
    {
        let maxflow = g.ford_fulkerson(0, 5);
        assert_eq!(2.0, maxflow.value());
    }
    // println!("maxflow => \n{}", g.to_dot());
}
<commit_msg>maximum_flow: minor changes<commit_after>use std::fmt;
use std::iter;
use std::f64;
use std::sync::{Arc, RwLock};

use adivon::bag::Bag;
use adivon::queue::Queue;

/// Capacitated edge with a flow in a flow network.
pub struct FlowEdge {
    v: usize,                   // from
    w: usize,                   // to
    capacity: f64,
    flow: f64
}

impl FlowEdge {
    pub fn new(v: usize, w: usize, capacity: f64) -> FlowEdge {
        assert!(capacity >= 0.0, "edge capacity must be non-negative");
        FlowEdge {
            v: v,
            w: w,
            capacity: capacity,
            flow: 0.0
        }
    }

    pub fn new_with_flow(v: usize, w: usize, capacity: f64, flow: f64) -> FlowEdge {
        assert!(capacity >= 0.0, "edge capacity must be non-negative");
        assert!(flow <= capacity, "flow exceeds capacity");
        assert!(flow >= 0.0, "flow must be non-negative");
        FlowEdge {
            v: v,
            w: w,
            capacity: capacity,
            flow: flow
        }
    }

    pub fn from(&self) -> usize {
        self.v
    }

    pub fn to(&self) -> usize {
        self.w
    }

    pub fn capacity(&self) -> f64 {
        self.capacity
    }

    pub fn flow(&self) -> f64 {
        self.flow
    }

    pub fn other(&self, vertex: usize) -> usize {
        if vertex == self.v {
            self.w
        } else if vertex == self.w {
            self.v
        } else {
            panic!("illegal endpoint")
        }
    }

    pub fn residual_capacity_to(&self, vertex: usize) -> f64 {
        if vertex == self.v {
            self.flow
        } else if vertex == self.w {
            self.capacity - self.flow
        } else {
            panic!("illegal endpoint")
        }
    }

    pub fn add_residual_flow_to(&mut self, vertex: usize, delta: f64) {
        assert!(!delta.is_nan(), "change in flow = NaN");
        if vertex == self.v {
            self.flow -= delta;
        } else if vertex == self.w {
            self.flow += delta;
        } else {
            panic!("illegal endpoint")
        }
        assert!(self.flow >= 0.0 && self.flow <= self.capacity)
    }
}

impl fmt::Debug for FlowEdge {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} -> {} {}/{}", self.v, self.w, self.flow, self.capacity)
    }
}

#[test]
fn test_flow_edge() {
    let e = FlowEdge::new(12, 23, 3.14);
    assert_eq!("12 -> 23 0/3.14", format!("{:?}", e));
}

/// A capacitated flow network, implemented using adjacency lists.
pub struct FlowNetwork {
    v: usize,
    e: usize,
    adj: Vec<Bag<Arc<RwLock<FlowEdge>>>>
}

impl FlowNetwork {
    pub fn new(v: usize) -> FlowNetwork {
        FlowNetwork {
            v: v,
            e: 0,
            adj: iter::repeat(Bag::new()).take(v).collect()
        }
    }

    pub fn v(&self) -> usize {
        self.v
    }

    pub fn e(&self) -> usize {
        self.e
    }

    fn validate_vertex(&self, v: usize) {
        assert!(v < self.v())
    }

    pub fn add_edge(&mut self, e: FlowEdge) {
        let v = e.from();
        let w = e.to();
        self.validate_vertex(v);
        self.validate_vertex(w);
        let edge = Arc::new(RwLock::new(e));
        self.adj[v].add(edge.clone());
        self.adj[w].add(edge);
        self.e += 1;
    }

    pub fn adj<'r>(&'r self, v: usize) -> Vec<Arc<RwLock<FlowEdge>>> {
        self.validate_vertex(v);
        self.adj[v].iter().map(|e| e.clone()).collect()
    }

    pub fn edges<'r>(&'r self) -> Vec<Arc<RwLock<FlowEdge>>> {
        self.adj.iter()
            .flat_map(|adj| {
                adj.iter()
                    .map(|e| e.clone())
                    .collect::<Vec<Arc<RwLock<FlowEdge>>>>()
                    .into_iter()
            })
            .collect()
    }

    pub fn to_dot(&self) -> String {
        let mut dot = String::new();

        dot.push_str("digraph G {\n");
        for i in 0 .. self.v {
            dot.push_str(&format!("  {};\n", i));
        }

        for v in 0 .. self.v() {
            for e in self.adj(v) {
                let e = e.read().unwrap();
                if v == e.from() {
                    let w = e.to();
                    dot.push_str(&format!("  {} -> {} [ label=\"{}/{}\" ];\n",
                                          v, w, e.flow, e.capacity));
                }
            }
        }
        dot.push_str("}\n");
        dot
    }
}

/// Ford-Fulkerson algorithm for computing a max flow and
/// a min cut using shortest augmenting path rule.
pub struct FordFulkerson<'g> {
    graph: &'g FlowNetwork,
    marked: Vec<bool>,
    edge_to: Vec<Option<Arc<RwLock<FlowEdge>>>>,
    value: f64
}

impl<'g> FordFulkerson<'g> {
    fn new<'a>(graph: &'a FlowNetwork, s: usize, t: usize) -> FordFulkerson<'a> {
        graph.validate_vertex(s);
        graph.validate_vertex(t);

        let mut ret = FordFulkerson {
            graph: graph,
            marked: Vec::new(), // will init in has_augmenting_path()
            edge_to: Vec::new(), // as above
            value: 0.0
        };
        ret.ford_fulkerson(s, t);
        ret
    }

    fn ford_fulkerson(&mut self, s: usize, t: usize) {
        if !self.is_feasible(s, t) {
            panic!("initial flow is infeasible");
        }

        self.value = self.excess(t);
        while self.has_augmenting_path(s, t) {
            let mut bottle = f64::INFINITY;
            let mut v = t;
            while v != s {
                let ee = self.edge_to[v].as_ref().unwrap().clone();
                bottle = bottle.min(ee.write().unwrap().residual_capacity_to(v));
                v = ee.read().unwrap().other(v);
            }

            // augment flow
            let mut v = t;
            while v != s {
                let ee = self.edge_to[v].as_ref().unwrap().clone();
                ee.write().unwrap().add_residual_flow_to(v, bottle);
                v = ee.read().unwrap().other(v);
            }

            self.value += bottle;
        }
    }

    pub fn value(&self) -> f64 {
        self.value
    }

    // is v in the s side of the min s-t cut?
    pub fn in_cut(&self, v: usize) -> bool {
        self.graph.validate_vertex(v);
        self.marked[v]
    }

    // is there an augmenting path?
    fn has_augmenting_path(&mut self, s: usize, t: usize) -> bool {
        self.edge_to = iter::repeat(None).take(self.graph.v()).collect();
        self.marked = iter::repeat(false).take(self.graph.v()).collect();

        let mut queue = Queue::<usize>::new();
        queue.enqueue(s);
        self.marked[s] = true;
        while !queue.is_empty() && !self.marked[t] {
            let v = queue.dequeue().unwrap();

            for ee in self.graph.adj(v) {
                let e = ee.read().unwrap();
                let w = e.other(v);

                // if residual capacity from v to w
                if e.residual_capacity_to(w) > 0.0 {
                    if !self.marked[w] {
                        self.edge_to[w] = Some(ee.clone());
                        self.marked[w] = true;
                        queue.enqueue(w);
                    }
                }
            }
        }
        self.marked[t]
    }

    // return excess flow at vertex v
    fn excess(&self, v: usize) -> f64 {
        let mut excess = 0f64;
        for e in self.graph.adj(v) {
            let e = e.read().unwrap();
            if v == e.from() {
                excess -= e.flow();
            } else {
                excess += e.flow();
            }
        }
        excess
    }

    fn is_feasible(&self, s: usize, t: usize) -> bool {
        const EPSILON: f64 = 1e-11;

        // check that capacity constraints are satisfied
        for v in 0 .. self.graph.v() {
            for e in self.graph.adj(v) {
                let e = e.read().unwrap();
                if e.flow() < -EPSILON || e.flow() > e.capacity() + EPSILON {
                    panic!("edge does not satisfy capacity constraints");
                    // return false;
                }
            }
        }

        // check that net flow into a vertex equals zero, except at source and sink
        if (self.value + self.excess(s)).abs() > EPSILON {
            panic!("Excess at source = {}", self.excess(s));
            // return false;
        }

        for v in 0 .. self.graph.v() {
            if v == s || v == t {
                continue;
            } else {
                if self.excess(v).abs() > EPSILON {
                    panic!("net flow out of {:?} doesn't equal zero", v);
                    // return false;
                }
            }
        }
        return true;
    }
}

impl FlowNetwork {
    pub fn ford_fulkerson<'a>(&'a mut self, s: usize, t: usize) -> FordFulkerson<'a> {
        assert!(s != t, "source equal to sink");
        FordFulkerson::new(self, s, t)
    }
}

#[test]
fn test_flow_network() {
    let mut g = FlowNetwork::new(6);

    g.add_edge(FlowEdge::new(0, 1, 2.0));
    g.add_edge(FlowEdge::new(0, 2, 3.0));
    g.add_edge(FlowEdge::new(1, 3, 3.0));
    g.add_edge(FlowEdge::new(1, 4, 1.0));
    g.add_edge(FlowEdge::new(2, 3, 1.0));
    g.add_edge(FlowEdge::new(2, 4, 1.0));
    g.add_edge(FlowEdge::new(3, 5, 2.0));
    g.add_edge(FlowEdge::new(4, 3, 3.0));

    // println!("=> \n{}", g.to_dot());
    {
        let maxflow = g.ford_fulkerson(0, 5);
        assert_eq!(2.0, maxflow.value());
    }
    // println!("maxflow => \n{}", g.to_dot());
}
<|endoftext|>


<commit_before>//! Developer note:
//!
//! This is a set of embed builders for rich embeds.
//!
//! These are used in the [`ChannelId::send_message`] and
//! [`ExecuteWebhook::embeds`] methods, both as part of builders.
//!
//! The only builder that should be exposed is [`CreateEmbed`]. The rest of
//! these have no real reason for being exposed, but are for completeness' sake.
//!
//! Documentation for embeds can be found [here].
//!
//! [`ChannelId::send_message`]: ../model/id/struct.ChannelId.html#method.send_message
//! [`CreateEmbed`]: struct.CreateEmbed.html
//! [`ExecuteWebhook::embeds`]: struct.ExecuteWebhook.html#method.embeds
//! [here]: https://discordapp.com/developers/docs/resources/channel#embed-object

use chrono::{DateTime, TimeZone};
use internal::prelude::*;
use model::channel::Embed;
use serde_json::Value;
use std::default::Default;
use std::fmt::Display;
use utils;
use utils::VecMap;

#[cfg(feature = "utils")]
use utils::Colour;

/// A builder to create a fake [`Embed`] object, for use with the
/// [`ChannelId::send_message`] and [`ExecuteWebhook::embeds`] methods.
///
/// # Examples
///
/// Refer to the documentation for [`ChannelId::send_message`] for a very in-depth
/// example on how to use this.
///
/// [`ChannelId::send_message`]: ../model/id/struct.ChannelId.html#method.send_message
/// [`Embed`]: ../model/channel/struct.Embed.html
/// [`ExecuteWebhook::embeds`]: struct.ExecuteWebhook.html#method.embeds
#[derive(Clone, Debug)]
pub struct CreateEmbed(pub VecMap<&'static str, Value>);

impl CreateEmbed {
    /// Set the author of the embed.
    ///
    /// Refer to the documentation for [`CreateEmbedAuthor`] for more
    /// information.
    ///
    /// [`CreateEmbedAuthor`]: struct.CreateEmbedAuthor.html
    pub fn author<F>(mut self, f: F) -> Self
        where F: FnOnce(CreateEmbedAuthor) -> CreateEmbedAuthor {
        let map = utils::vecmap_to_json_map(f(CreateEmbedAuthor::default()).0);

        self.0.insert("author", Value::Object(map));

        CreateEmbed(self.0)
    }

    /// Set the colour of the left-hand side of the embed.
    ///
    /// This is an alias of [`colour`].
    ///
    /// [`colour`]: #method.colour
    #[cfg(feature = "utils")]
    #[inline]
    pub fn color<C: Into<Colour>>(self, colour: C) -> Self { self.colour(colour.into()) }

    /// Set the colour of the left-hand side of the embed.
    #[cfg(feature = "utils")]
    pub fn colour<C: Into<Colour>>(mut self, colour: C) -> Self {
        self.0.insert(
            "color",
            Value::Number(Number::from(u64::from(colour.into().0))),
        );

        CreateEmbed(self.0)
    }

    /// Set the colour of the left-hand side of the embed.
    ///
    /// This is an alias of [`colour`].
    ///
    /// [`colour`]: #method.colour
    #[cfg(not(feature = "utils"))]
    #[inline]
    pub fn color(self, colour: u32) -> Self { self.colour(colour) }

    /// Set the colour of the left-hand side of the embed.
    #[cfg(not(feature = "utils"))]
    pub fn colour(mut self, colour: u32) -> Self {
        self.0
            .insert("color", Value::Number(Number::from(colour)));

        CreateEmbed(self.0)
    }

    /// Set the description of the embed.
    ///
    /// **Note**: This can't be longer than 2048 characters.
    pub fn description<D: Display>(mut self, description: D) -> Self {
        self.0.insert(
            "description",
            Value::String(description.to_string()),
        );

        CreateEmbed(self.0)
    }

    /// Set a field. Note that this will not overwrite other fields, and will
    /// add to them.
    ///
    /// Refer to the documentation for [`CreateEmbedField`] for more
    /// information.
    ///
    /// **Note**: Maximum amount of characters you can put is 256 in a field
    /// name and 1024 in a field value and a field is inline by default.
    ///
    /// [`CreateEmbedField`]: struct.CreateEmbedField.html
    pub fn field<T, U>(mut self, name: T, value: U, inline: bool) -> Self
        where T: Display, U: Display {
        {
            let entry = self.0
                .entry("fields")
                .or_insert_with(|| Value::Array(vec![]));

            if let Value::Array(ref mut inner) = *entry {
                inner.push(json!({
                    "inline": inline,
                    "name": name.to_string(),
                    "value": value.to_string(),
                }));
            }
        }

        self
    }

    /// Adds multiple fields at once.
    pub fn fields<T, U, It>(mut self, fields: It) -> Self
        where It: IntoIterator<Item=(T, U, bool)>,
              T: Display,
              U: Display {
        for field in fields {
            self = self.field(field.0.to_string(), field.1.to_string(), field.2);
        }

        self
    }

    /// Set the footer of the embed.
    ///
    /// Refer to the documentation for [`CreateEmbedFooter`] for more
    /// information.
    ///
    /// [`CreateEmbedFooter`]: struct.CreateEmbedFooter.html
    pub fn footer<F>(mut self, f: F) -> Self
        where F: FnOnce(CreateEmbedFooter) -> CreateEmbedFooter {
        let footer = f(CreateEmbedFooter::default()).0;
        let map = utils::vecmap_to_json_map(footer);

        self.0.insert("footer", Value::Object(map));

        CreateEmbed(self.0)
    }

    fn url_object(mut self, name: &'static str, url: &str) -> Self {
        let obj = json!({
            "url": url.to_string()
        });

        self.0.insert(name, obj);

        CreateEmbed(self.0)
    }

    /// Set the image associated with the embed. This only supports HTTP(S).
    #[inline]
    pub fn image(self, url: &str) -> Self {
        self.url_object("image", url)
    }

    /// Set the video associated with the embed. This only supports HTTP(S).
    #[inline]
    pub fn video(self, url: &str) -> Self {
        self.url_object("video", url)
    }

    /// Set the thumbnail of the embed. This only supports HTTP(S).
    #[inline]
    pub fn thumbnail(self, url: &str) -> Self {
        self.url_object("thumbnail", url)
    }

    /// Set the timestamp.
    ///
    /// You may pass a direct string:
    ///
    /// - `2017-01-03T23:00:00`
    /// - `2004-06-08T16:04:23`
    /// - `2004-06-08T16:04:23`
    ///
    /// This timestamp must be in ISO-8601 format. It must also be in UTC format.
    ///
    /// You can also pass anything that implements `chrono::TimeZone`.
    ///
    /// # Examples
    ///
    /// Passing a string timestamp:
    ///
    /// ```rust,no_run
    /// use serenity::prelude::*;
    /// use serenity::model::channel::Message;
    ///
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, _: Context, msg: Message) {
    ///         if msg.content == "~embed" {
    ///             let _ = msg.channel_id.send_message(|m| m
    ///              .embed(|e| e
    ///                     .title("hello")
    ///                     .timestamp("2004-06-08T16:04:23")));
    ///         }
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// Creating a join-log:
    ///
    /// Note: this example isn't efficient and is for demonstrative purposes.
    ///
    /// ```rust,no_run
    /// use serenity::prelude::*;
    /// use serenity::model::guild::Member;
    /// use serenity::model::id::GuildId;
    ///
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn guild_member_addition(&self, _: Context, guild_id: GuildId, member: Member) {
    ///         use serenity::CACHE;
    ///         let cache = CACHE.read();
    ///
    ///         if let Some(guild) = cache.guild(guild_id) {
    ///             let guild = guild.read();
    ///
    ///             let channel_search = guild
    ///                 .channels
    ///                 .values()
    ///                 .find(|c| c.read().name == "join-log");
    ///
    ///             if let Some(channel) = channel_search {
    ///                 let user = member.user.read();
    ///
    ///                 let _ = channel.read().send_message(|m| m
    ///                     .embed(|e| {
    ///                         let mut e = e
    ///                             .author(|a| a.icon_url(&user.face()).name(&user.name))
    ///                             .title("Member Join");
    ///
    ///                         if let Some(ref joined_at) = member.joined_at {
    ///                             e = e.timestamp(joined_at);
    ///                         }
    ///
    ///                         e
    ///                     }));
    ///             }
    ///         }
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    pub fn timestamp<T: Into<Timestamp>>(mut self, timestamp: T) -> Self {
        self.0
            .insert("timestamp", Value::String(timestamp.into().ts));

        CreateEmbed(self.0)
    }

    /// Set the title of the embed.
    pub fn title<D: Display>(mut self, title: D) -> Self {
        self.0
            .insert("title", Value::String(title.to_string()));

        CreateEmbed(self.0)
    }

    /// Set the URL to direct to when clicking on the title.
    pub fn url(mut self, url: &str) -> Self {
        self.0
            .insert("url", Value::String(url.to_string()));

        CreateEmbed(self.0)
    }

    /// Same as calling [`image`] with "attachment://filename.(jpg, png)".
    ///
    /// Note however, you have to be sure you set an attachment (with [`ChannelId::send_files`])
    /// with the provided filename. Or else this won't work.
    ///
    /// [`ChannelId::send_files`]: ../model/id/struct.ChannelId.html#send_files
    pub fn attachment(self, filename: &str) -> Self {
        self.image(&format!("attachment://{}", filename))
    }
}

impl Default for CreateEmbed {
    /// Creates a builder with default values, setting the `type` to `rich`.
    fn default() -> CreateEmbed {
        let mut map = VecMap::new();
        map.insert("type", Value::String("rich".to_string()));

        CreateEmbed(map)
    }
}

impl From<Embed> for CreateEmbed {
    /// Converts the fields of an embed into the values for a new embed builder.
    ///
    /// Some values - such as Proxy URLs - are not preserved.
    fn from(embed: Embed) -> CreateEmbed {
        let mut b = CreateEmbed::default().colour(embed.colour);

        if let Some(author) = embed.author {
            b = b.author(move |mut a| {
                a = a.name(&author.name);

                if let Some(icon_url) = author.icon_url {
                    a = a.icon_url(&icon_url);
                }

                if let Some(url) = author.url {
                    a = a.url(&url);
                }

                a
            });
        }

        if let Some(description) = embed.description {
            b = b.description(&description);
        }

        for field in embed.fields {
            b = b.field(field.name, field.value, field.inline);
        }

        if let Some(image) = embed.image {
            b = b.image(&image.url);
        }

        if let Some(timestamp) = embed.timestamp {
            b = b.timestamp(timestamp);
        }

        if let Some(thumbnail) = embed.thumbnail {
            b = b.thumbnail(&thumbnail.url);
        }

        if let Some(url) = embed.url {
            b = b.url(&url);
        }

        if let Some(title) = embed.title {
            b = b.title(&title);
        }

        if let Some(footer) = embed.footer {
            b = b.footer(move |mut f| {
                f = f.text(&footer.text);

                if let Some(icon_url) = footer.icon_url {
                    f = f.icon_url(&icon_url);
                }

                f
            });
        }

        b
    }
}

/// A builder to create a fake [`Embed`] object's author, for use with the
/// [`CreateEmbed::author`] method.
///
/// Requires that you specify a [`name`].
///
/// [`Embed`]: ../model/channel/struct.Embed.html
/// [`CreateEmbed::author`]: struct.CreateEmbed.html#method.author
/// [`name`]: #method.name
#[derive(Clone, Debug, Default)]
pub struct CreateEmbedAuthor(pub VecMap<&'static str, Value>);

impl CreateEmbedAuthor {
    /// Set the URL of the author's icon.
    pub fn icon_url(mut self, icon_url: &str) -> Self {
        self.0.insert("icon_url", Value::String(icon_url.to_string()));

        self
    }

    /// Set the author's name.
    pub fn name(mut self, name: &str) -> Self {
        self.0.insert("name", Value::String(name.to_string()));

        self
    }

    /// Set the author's URL.
    pub fn url(mut self, url: &str) -> Self {
        self.0.insert("url", Value::String(url.to_string()));

        self
    }
}

/// A builder to create a fake [`Embed`] object's footer, for use with the
/// [`CreateEmbed::footer`] method.
///
/// This does not require any field be set.
///
/// [`Embed`]: ../model/channel/struct.Embed.html
/// [`CreateEmbed::footer`]: struct.CreateEmbed.html#method.footer
#[derive(Clone, Debug, Default)]
pub struct CreateEmbedFooter(pub VecMap<&'static str, Value>);

impl CreateEmbedFooter {
    /// Set the icon URL's value. This only supports HTTP(S).
    pub fn icon_url(mut self, icon_url: &str) -> Self {
        self.0.insert("icon_url", Value::String(icon_url.to_string()));

        self
    }

    /// Set the footer's text.
    pub fn text<D: Display>(mut self, text: D) -> Self {
        self.0.insert("text", Value::String(text.to_string()));

        self
    }
}

#[derive(Clone, Debug)]
pub struct Timestamp {
    pub ts: String,
}

impl From<String> for Timestamp {
    fn from(ts: String) -> Self {
        Timestamp {
            ts: ts,
        }
    }
}

impl<'a> From<&'a str> for Timestamp {
    fn from(ts: &'a str) -> Self {
        Timestamp {
            ts: ts.to_string(),
        }
    }
}

impl<'a, Tz: TimeZone> From<&'a DateTime<Tz>> for Timestamp
    where Tz::Offset: Display {
    fn from(dt: &'a DateTime<Tz>) -> Self {
        Timestamp {
            ts: dt.to_rfc3339(),
        }
    }
}
<commit_msg>Partially revert the video url change<commit_after>//! Developer note:
//!
//! This is a set of embed builders for rich embeds.
//!
//! These are used in the [`ChannelId::send_message`] and
//! [`ExecuteWebhook::embeds`] methods, both as part of builders.
//!
//! The only builder that should be exposed is [`CreateEmbed`]. The rest of
//! these have no real reason for being exposed, but are for completeness' sake.
//!
//! Documentation for embeds can be found [here].
//!
//! [`ChannelId::send_message`]: ../model/id/struct.ChannelId.html#method.send_message
//! [`CreateEmbed`]: struct.CreateEmbed.html
//! [`ExecuteWebhook::embeds`]: struct.ExecuteWebhook.html#method.embeds
//! [here]: https://discordapp.com/developers/docs/resources/channel#embed-object

use chrono::{DateTime, TimeZone};
use internal::prelude::*;
use model::channel::Embed;
use serde_json::Value;
use std::default::Default;
use std::fmt::Display;
use utils;
use utils::VecMap;

#[cfg(feature = "utils")]
use utils::Colour;

/// A builder to create a fake [`Embed`] object, for use with the
/// [`ChannelId::send_message`] and [`ExecuteWebhook::embeds`] methods.
///
/// # Examples
///
/// Refer to the documentation for [`ChannelId::send_message`] for a very in-depth
/// example on how to use this.
///
/// [`ChannelId::send_message`]: ../model/id/struct.ChannelId.html#method.send_message
/// [`Embed`]: ../model/channel/struct.Embed.html
/// [`ExecuteWebhook::embeds`]: struct.ExecuteWebhook.html#method.embeds
#[derive(Clone, Debug)]
pub struct CreateEmbed(pub VecMap<&'static str, Value>);

impl CreateEmbed {
    /// Set the author of the embed.
    ///
    /// Refer to the documentation for [`CreateEmbedAuthor`] for more
    /// information.
    ///
    /// [`CreateEmbedAuthor`]: struct.CreateEmbedAuthor.html
    pub fn author<F>(mut self, f: F) -> Self
        where F: FnOnce(CreateEmbedAuthor) -> CreateEmbedAuthor {
        let map = utils::vecmap_to_json_map(f(CreateEmbedAuthor::default()).0);

        self.0.insert("author", Value::Object(map));

        CreateEmbed(self.0)
    }

    /// Set the colour of the left-hand side of the embed.
    ///
    /// This is an alias of [`colour`].
    ///
    /// [`colour`]: #method.colour
    #[cfg(feature = "utils")]
    #[inline]
    pub fn color<C: Into<Colour>>(self, colour: C) -> Self { self.colour(colour.into()) }

    /// Set the colour of the left-hand side of the embed.
    #[cfg(feature = "utils")]
    pub fn colour<C: Into<Colour>>(mut self, colour: C) -> Self {
        self.0.insert(
            "color",
            Value::Number(Number::from(u64::from(colour.into().0))),
        );

        CreateEmbed(self.0)
    }

    /// Set the colour of the left-hand side of the embed.
    ///
    /// This is an alias of [`colour`].
    ///
    /// [`colour`]: #method.colour
    #[cfg(not(feature = "utils"))]
    #[inline]
    pub fn color(self, colour: u32) -> Self { self.colour(colour) }

    /// Set the colour of the left-hand side of the embed.
    #[cfg(not(feature = "utils"))]
    pub fn colour(mut self, colour: u32) -> Self {
        self.0
            .insert("color", Value::Number(Number::from(colour)));

        CreateEmbed(self.0)
    }

    /// Set the description of the embed.
    ///
    /// **Note**: This can't be longer than 2048 characters.
    pub fn description<D: Display>(mut self, description: D) -> Self {
        self.0.insert(
            "description",
            Value::String(description.to_string()),
        );

        CreateEmbed(self.0)
    }

    /// Set a field. Note that this will not overwrite other fields, and will
    /// add to them.
    ///
    /// Refer to the documentation for [`CreateEmbedField`] for more
    /// information.
    ///
    /// **Note**: Maximum amount of characters you can put is 256 in a field
    /// name and 1024 in a field value and a field is inline by default.
    ///
    /// [`CreateEmbedField`]: struct.CreateEmbedField.html
    pub fn field<T, U>(mut self, name: T, value: U, inline: bool) -> Self
        where T: Display, U: Display {
        {
            let entry = self.0
                .entry("fields")
                .or_insert_with(|| Value::Array(vec![]));

            if let Value::Array(ref mut inner) = *entry {
                inner.push(json!({
                    "inline": inline,
                    "name": name.to_string(),
                    "value": value.to_string(),
                }));
            }
        }

        self
    }

    /// Adds multiple fields at once.
    pub fn fields<T, U, It>(mut self, fields: It) -> Self
        where It: IntoIterator<Item=(T, U, bool)>,
              T: Display,
              U: Display {
        for field in fields {
            self = self.field(field.0.to_string(), field.1.to_string(), field.2);
        }

        self
    }

    /// Set the footer of the embed.
    ///
    /// Refer to the documentation for [`CreateEmbedFooter`] for more
    /// information.
    ///
    /// [`CreateEmbedFooter`]: struct.CreateEmbedFooter.html
    pub fn footer<F>(mut self, f: F) -> Self
        where F: FnOnce(CreateEmbedFooter) -> CreateEmbedFooter {
        let footer = f(CreateEmbedFooter::default()).0;
        let map = utils::vecmap_to_json_map(footer);

        self.0.insert("footer", Value::Object(map));

        CreateEmbed(self.0)
    }

    fn url_object(mut self, name: &'static str, url: &str) -> Self {
        let obj = json!({
            "url": url.to_string()
        });

        self.0.insert(name, obj);

        CreateEmbed(self.0)
    }

    /// Set the image associated with the embed. This only supports HTTP(S).
    #[inline]
    pub fn image(self, url: &str) -> Self {
        self.url_object("image", url)
    }

    /// Set the thumbnail of the embed. This only supports HTTP(S).
    #[inline]
    pub fn thumbnail(self, url: &str) -> Self {
        self.url_object("thumbnail", url)
    }

    /// Set the timestamp.
    ///
    /// You may pass a direct string:
    ///
    /// - `2017-01-03T23:00:00`
    /// - `2004-06-08T16:04:23`
    /// - `2004-06-08T16:04:23`
    ///
    /// This timestamp must be in ISO-8601 format. It must also be in UTC format.
    ///
    /// You can also pass anything that implements `chrono::TimeZone`.
    ///
    /// # Examples
    ///
    /// Passing a string timestamp:
    ///
    /// ```rust,no_run
    /// use serenity::prelude::*;
    /// use serenity::model::channel::Message;
    ///
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, _: Context, msg: Message) {
    ///         if msg.content == "~embed" {
    ///             let _ = msg.channel_id.send_message(|m| m
    ///              .embed(|e| e
    ///                     .title("hello")
    ///                     .timestamp("2004-06-08T16:04:23")));
    ///         }
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// Creating a join-log:
    ///
    /// Note: this example isn't efficient and is for demonstrative purposes.
    ///
    /// ```rust,no_run
    /// use serenity::prelude::*;
    /// use serenity::model::guild::Member;
    /// use serenity::model::id::GuildId;
    ///
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn guild_member_addition(&self, _: Context, guild_id: GuildId, member: Member) {
    ///         use serenity::CACHE;
    ///         let cache = CACHE.read();
    ///
    ///         if let Some(guild) = cache.guild(guild_id) {
    ///             let guild = guild.read();
    ///
    ///             let channel_search = guild
    ///                 .channels
    ///                 .values()
    ///                 .find(|c| c.read().name == "join-log");
    ///
    ///             if let Some(channel) = channel_search {
    ///                 let user = member.user.read();
    ///
    ///                 let _ = channel.read().send_message(|m| m
    ///                     .embed(|e| {
    ///                         let mut e = e
    ///                             .author(|a| a.icon_url(&user.face()).name(&user.name))
    ///                             .title("Member Join");
    ///
    ///                         if let Some(ref joined_at) = member.joined_at {
    ///                             e = e.timestamp(joined_at);
    ///                         }
    ///
    ///                         e
    ///                     }));
    ///             }
    ///         }
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    pub fn timestamp<T: Into<Timestamp>>(mut self, timestamp: T) -> Self {
        self.0
            .insert("timestamp", Value::String(timestamp.into().ts));

        CreateEmbed(self.0)
    }

    /// Set the title of the embed.
    pub fn title<D: Display>(mut self, title: D) -> Self {
        self.0
            .insert("title", Value::String(title.to_string()));

        CreateEmbed(self.0)
    }

    /// Set the URL to direct to when clicking on the title.
    pub fn url(mut self, url: &str) -> Self {
        self.0
            .insert("url", Value::String(url.to_string()));

        CreateEmbed(self.0)
    }

    /// Same as calling [`image`] with "attachment://filename.(jpg, png)".
    ///
    /// Note however, you have to be sure you set an attachment (with [`ChannelId::send_files`])
    /// with the provided filename. Or else this won't work.
    ///
    /// [`ChannelId::send_files`]: ../model/id/struct.ChannelId.html#send_files
    pub fn attachment(self, filename: &str) -> Self {
        self.image(&format!("attachment://{}", filename))
    }
}

impl Default for CreateEmbed {
    /// Creates a builder with default values, setting the `type` to `rich`.
    fn default() -> CreateEmbed {
        let mut map = VecMap::new();
        map.insert("type", Value::String("rich".to_string()));

        CreateEmbed(map)
    }
}

impl From<Embed> for CreateEmbed {
    /// Converts the fields of an embed into the values for a new embed builder.
    ///
    /// Some values - such as Proxy URLs - are not preserved.
    fn from(embed: Embed) -> CreateEmbed {
        let mut b = CreateEmbed::default().colour(embed.colour);

        if let Some(author) = embed.author {
            b = b.author(move |mut a| {
                a = a.name(&author.name);

                if let Some(icon_url) = author.icon_url {
                    a = a.icon_url(&icon_url);
                }

                if let Some(url) = author.url {
                    a = a.url(&url);
                }

                a
            });
        }

        if let Some(description) = embed.description {
            b = b.description(&description);
        }

        for field in embed.fields {
            b = b.field(field.name, field.value, field.inline);
        }

        if let Some(image) = embed.image {
            b = b.image(&image.url);
        }

        if let Some(timestamp) = embed.timestamp {
            b = b.timestamp(timestamp);
        }

        if let Some(thumbnail) = embed.thumbnail {
            b = b.thumbnail(&thumbnail.url);
        }

        if let Some(url) = embed.url {
            b = b.url(&url);
        }

        if let Some(title) = embed.title {
            b = b.title(&title);
        }

        if let Some(footer) = embed.footer {
            b = b.footer(move |mut f| {
                f = f.text(&footer.text);

                if let Some(icon_url) = footer.icon_url {
                    f = f.icon_url(&icon_url);
                }

                f
            });
        }

        b
    }
}

/// A builder to create a fake [`Embed`] object's author, for use with the
/// [`CreateEmbed::author`] method.
///
/// Requires that you specify a [`name`].
///
/// [`Embed`]: ../model/channel/struct.Embed.html
/// [`CreateEmbed::author`]: struct.CreateEmbed.html#method.author
/// [`name`]: #method.name
#[derive(Clone, Debug, Default)]
pub struct CreateEmbedAuthor(pub VecMap<&'static str, Value>);

impl CreateEmbedAuthor {
    /// Set the URL of the author's icon.
    pub fn icon_url(mut self, icon_url: &str) -> Self {
        self.0.insert("icon_url", Value::String(icon_url.to_string()));

        self
    }

    /// Set the author's name.
    pub fn name(mut self, name: &str) -> Self {
        self.0.insert("name", Value::String(name.to_string()));

        self
    }

    /// Set the author's URL.
    pub fn url(mut self, url: &str) -> Self {
        self.0.insert("url", Value::String(url.to_string()));

        self
    }
}

/// A builder to create a fake [`Embed`] object's footer, for use with the
/// [`CreateEmbed::footer`] method.
///
/// This does not require any field be set.
///
/// [`Embed`]: ../model/channel/struct.Embed.html
/// [`CreateEmbed::footer`]: struct.CreateEmbed.html#method.footer
#[derive(Clone, Debug, Default)]
pub struct CreateEmbedFooter(pub VecMap<&'static str, Value>);

impl CreateEmbedFooter {
    /// Set the icon URL's value. This only supports HTTP(S).
    pub fn icon_url(mut self, icon_url: &str) -> Self {
        self.0.insert("icon_url", Value::String(icon_url.to_string()));

        self
    }

    /// Set the footer's text.
    pub fn text<D: Display>(mut self, text: D) -> Self {
        self.0.insert("text", Value::String(text.to_string()));

        self
    }
}

#[derive(Clone, Debug)]
pub struct Timestamp {
    pub ts: String,
}

impl From<String> for Timestamp {
    fn from(ts: String) -> Self {
        Timestamp {
            ts: ts,
        }
    }
}

impl<'a> From<&'a str> for Timestamp {
    fn from(ts: &'a str) -> Self {
        Timestamp {
            ts: ts.to_string(),
        }
    }
}

impl<'a, Tz: TimeZone> From<&'a DateTime<Tz>> for Timestamp
    where Tz::Offset: Display {
    fn from(dt: &'a DateTime<Tz>) -> Self {
        Timestamp {
            ts: dt.to_rfc3339(),
        }
    }
}
<|endoftext|>