<commit_before>#[macro_use]
extern crate error_chain;

use std::path::{Path,PathBuf};
use std::process::{Command,ExitStatus};
use std::io;
use std::fs::{self, DirEntry};
use std::borrow::ToOwned;

error_chain!{
    foreign_links {
        Io(::std::io::Error);
    }
    errors{
        MissingSourceDir{
            description("Couldn't locate source directory")
            display("Couldn't locate your source directory")
        }
        ForkFailure(command: &'static str){
            description("Failed to fork command")
            display("Failed to fork command {}",command)
        }
        ExitFailure(command: &'static str, status: ExitStatus){
            description("Command exited with failure status")
            display("Command {} exited with status: {}",command,status)
        }
        DistNotDir(dist_path: PathBuf){
            description("The dist path did not point to a directory")
            display("The path {:?} must not point to an existing non-directory file",dist_path)
        }
        NoSources(source_path: PathBuf){
            description("The located source path contains no source files")
            display("The located source path ({:?}) contained no `.java` files",source_path)
        }
    }
}

fn visit_dirs<P: AsRef<Path>,F: FnMut(&DirEntry)>(dir: P, cb: &mut F) -> io::Result<()> {
    let dir = dir.as_ref();
    if dir.is_dir() {
        for entry in try!(fs::read_dir(dir)) {
            let entry = try!(entry);
            let path = entry.path();
            if path.is_dir() {
                try!(visit_dirs(&path, cb));
            } else {
                cb(&entry);
            }
        }
    }
    Ok(())
}

fn find_in_dirs<P: AsRef<Path>,F:FnMut(&DirEntry) -> Option<T>,T>(dir: P, cb: &mut F) -> io::Result<Option<T>> {
    let dir = dir.as_ref();
    if dir.is_dir() {
        for entry in try!(fs::read_dir(dir)) {
            let entry = try!(entry);
            let path = entry.path();
            if path.is_dir() {
                match try!(find_in_dirs(&path, cb)){
                    Some(t) => return Ok(Some(t)),
                    None => continue
                }
            } else {
                match cb(&entry){
                    Some(t) => return Ok(Some(t)),
                    None => continue,
                }
            }
        }
    }
    Ok(None)
}

fn dir_exists<P: AsRef<Path>>(path: P) -> bool{
    let path = path.as_ref();
    path.exists() && path.is_dir()
}

fn source_root() -> Result<PathBuf>{
    const SEARCH_PATHS: &'static [&'static str] = &[
        "./src/main/java/",
        "./src/java/",
        "./src/"
    ];

    SEARCH_PATHS.iter().map(|&s| Path::new(s).to_path_buf()).find(|p| dir_exists(p)).ok_or(ErrorKind::MissingSourceDir.into())
}

fn libs_root() -> Option<PathBuf>{
    const SEARCH_PATHS: &'static [&'static str] = &[
        "./libs/",
        "./deps/"
    ];

    SEARCH_PATHS.iter().map(|&s| Path::new(s).to_path_buf()).find(|p| dir_exists(p))
}

fn find_files_by_extension<P: AsRef<Path>>(root_path: P,extension: &str, strip_root_prefix: bool) -> Result<Vec<PathBuf>>{
    let mut found = vec![];
    visit_dirs(root_path.as_ref(),&mut |entry: &DirEntry|{
        let path = entry.path();
        if path.extension().is_some() && path.extension().unwrap() == extension{
            let path = if strip_root_prefix {
                path.strip_prefix(&root_path).expect("Found something outside of $root_path in $root_path ???").to_path_buf()
            }else{
                path
            };
            found.push(path);
        }
    })?;
    Ok(found)
}

fn source_files<P: AsRef<Path>>(source_root: P) -> Result<Vec<PathBuf>>{
    find_files_by_extension(source_root,"java",false)
}

fn class_files() -> Result<Vec<PathBuf>>{
    find_files_by_extension("dist","class",true)
}

fn libs() -> Result<Vec<PathBuf>>{
    if let Some(dir) = libs_root(){
        find_files_by_extension(dir,"jar",false)
    }else{
        Ok(vec![])
    }
}

pub struct Kohi{
    dist_path: PathBuf,
    libs: Vec<PathBuf>,
    source_path: PathBuf,
    source_files: Vec<PathBuf>
}

impl Kohi{
    pub fn new() -> Result<Self>{
        let source_root = source_root()?;
        let source_files = source_files(&source_root)?;
        if source_files.len() == 0 {
            bail!(ErrorKind::NoSources(source_root));
        }
        Ok(Kohi{
            dist_path: Path::new("./dist/").to_path_buf(),
            libs: libs()?,
            source_path: source_root,
            source_files: source_files,
        })
    }

    pub fn compile<I: Into<Option<String>>>(self,target_version: I) -> Result<Self>{
        let classpath = std::env::join_paths(&self.libs).unwrap();

        if !self.dist_path.exists(){
            std::fs::create_dir_all(&self.dist_path)?;
        }else{
            if !self.dist_path.is_dir(){
                bail!(ErrorKind::DistNotDir(self.dist_path));
            }
        }

        let mut cmd = Command::new("javac");

        if let Some(target_version) = target_version.into(){
            cmd.arg("-source").arg(target_version).arg("-target").arg(target_version);
        }

        let status = cmd
            .arg("-d")
            .arg(&self.dist_path)
            .arg("-cp")
            .arg(classpath)
            .arg("-sourcepath")
            .arg(&self.source_path)
            .args(self.source_files.as_slice())
            .status()
            .chain_err(|| ErrorKind::ForkFailure("javac"))?;

        if status.success(){
            Ok(self)
        }else{
            bail!(ErrorKind::ExitFailure("javac",status))
        }
    }

    pub fn run(self, run_class: String) -> Result<Self>{
        //blah.class -> blah
        let run_class = run_class.trim_right_matches(".class");

        let classpath = std::env::join_paths(std::iter::once(&self.dist_path).chain(&self.libs)).unwrap();

        let main = self.find_class(run_class).expect("Couldn't locate the class to run");

        let status = Command::new("java")
                          .arg("-cp")
                          .arg(classpath)
                          .arg(main)
                          .status()
                          .chain_err(|| ErrorKind::ForkFailure("java"))?;

        if status.success(){
            Ok(self)
        }else{
            bail!(ErrorKind::ExitFailure("java",status))
        }
    }

    pub fn package(self, jar_name: &str, entry_point: Option<&str>) -> Result<Self>{
        let mut cmd = Command::new("jar");
        if let Some(entry_point) = entry_point{
            cmd.arg("-cfe")
                .arg(jar_name)
                .arg(entry_point);
        }else{
            cmd.arg("-cf")
                .arg(jar_name);
        }

        let status = cmd
            .arg("-C")
            .arg("dist")
            .args(class_files()?.as_slice())
            .status()
            .chain_err(|| ErrorKind::ForkFailure("jar"))?;

        if status.success(){
            Ok(self)
        }else{
            bail!(ErrorKind::ExitFailure("jar",status))
        }
    }

    fn find_class(&self,class: &str) -> Option<String>{

        let class = class.to_lowercase();
        let mut class_name: Vec<_> = class.split(".").map(ToOwned::to_owned).collect();

        //kinda hacky, but this means we don't have to continuously strip off the dist prefix in the loop
        class_name.insert(0,"dist".to_owned());

        //also a hack to avoid removing the ".class" from the last component constantly
        let len = class_name.len();
        class_name[len-1].push_str(".class");

        let path = find_in_dirs(self.dist_path.as_path(),&mut |entry|{
            let path = entry.path();
            {
                let components = path.components().filter_map(|comp|{
                    use std::path::Component;
                    match comp{
                        Component::Normal(str) => Some(str),
                        _ => None
                    }
                });

                for (a,b) in components.zip(class_name.iter()){
                    if let Some(a) = a.to_str().map(str::to_lowercase){
                        if &a == b{
                            continue
                        }else{
                            return None
                        }
                    }else{
                        return None
                    }
                }
            }
            Some(path)
        }).expect("IO Error while finding class file");

        if let Some(path) = path{
            let mut path = path.strip_prefix(self.dist_path.as_path()).expect("Found something outside of ./dist/ in ./dist/ ???").to_path_buf();
            path.set_extension("");

            let path: Vec<_> = path.iter().flat_map(|s| s.to_str()).map(|s| s.to_owned()).collect();
            let path = path.join(".");

            let path_as_class = path.trim_left_matches(".");
            Some(path_as_class.to_owned())
        }else{
            None
        }
    }
}<commit_msg>Forgot to clone<commit_after>#[macro_use]
extern crate error_chain;

use std::path::{Path,PathBuf};
use std::process::{Command,ExitStatus};
use std::io;
use std::fs::{self, DirEntry};
use std::borrow::ToOwned;

error_chain!{
    foreign_links {
        Io(::std::io::Error);
    }
    errors{
        MissingSourceDir{
            description("Couldn't locate source directory")
            display("Couldn't locate your source directory")
        }
        ForkFailure(command: &'static str){
            description("Failed to fork command")
            display("Failed to fork command {}",command)
        }
        ExitFailure(command: &'static str, status: ExitStatus){
            description("Command exited with failure status")
            display("Command {} exited with status: {}",command,status)
        }
        DistNotDir(dist_path: PathBuf){
            description("The dist path did not point to a directory")
            display("The path {:?} must not point to an existing non-directory file",dist_path)
        }
        NoSources(source_path: PathBuf){
            description("The located source path contains no source files")
            display("The located source path ({:?}) contained no `.java` files",source_path)
        }
    }
}

fn visit_dirs<P: AsRef<Path>,F: FnMut(&DirEntry)>(dir: P, cb: &mut F) -> io::Result<()> {
    let dir = dir.as_ref();
    if dir.is_dir() {
        for entry in try!(fs::read_dir(dir)) {
            let entry = try!(entry);
            let path = entry.path();
            if path.is_dir() {
                try!(visit_dirs(&path, cb));
            } else {
                cb(&entry);
            }
        }
    }
    Ok(())
}

fn find_in_dirs<P: AsRef<Path>,F:FnMut(&DirEntry) -> Option<T>,T>(dir: P, cb: &mut F) -> io::Result<Option<T>> {
    let dir = dir.as_ref();
    if dir.is_dir() {
        for entry in try!(fs::read_dir(dir)) {
            let entry = try!(entry);
            let path = entry.path();
            if path.is_dir() {
                match try!(find_in_dirs(&path, cb)){
                    Some(t) => return Ok(Some(t)),
                    None => continue
                }
            } else {
                match cb(&entry){
                    Some(t) => return Ok(Some(t)),
                    None => continue,
                }
            }
        }
    }
    Ok(None)
}

fn dir_exists<P: AsRef<Path>>(path: P) -> bool{
    let path = path.as_ref();
    path.exists() && path.is_dir()
}

fn source_root() -> Result<PathBuf>{
    const SEARCH_PATHS: &'static [&'static str] = &[
        "./src/main/java/",
        "./src/java/",
        "./src/"
    ];

    SEARCH_PATHS.iter().map(|&s| Path::new(s).to_path_buf()).find(|p| dir_exists(p)).ok_or(ErrorKind::MissingSourceDir.into())
}

fn libs_root() -> Option<PathBuf>{
    const SEARCH_PATHS: &'static [&'static str] = &[
        "./libs/",
        "./deps/"
    ];

    SEARCH_PATHS.iter().map(|&s| Path::new(s).to_path_buf()).find(|p| dir_exists(p))
}

fn find_files_by_extension<P: AsRef<Path>>(root_path: P,extension: &str, strip_root_prefix: bool) -> Result<Vec<PathBuf>>{
    let mut found = vec![];
    visit_dirs(root_path.as_ref(),&mut |entry: &DirEntry|{
        let path = entry.path();
        if path.extension().is_some() && path.extension().unwrap() == extension{
            let path = if strip_root_prefix {
                path.strip_prefix(&root_path).expect("Found something outside of $root_path in $root_path ???").to_path_buf()
            }else{
                path
            };
            found.push(path);
        }
    })?;
    Ok(found)
}

fn source_files<P: AsRef<Path>>(source_root: P) -> Result<Vec<PathBuf>>{
    find_files_by_extension(source_root,"java",false)
}

fn class_files() -> Result<Vec<PathBuf>>{
    find_files_by_extension("dist","class",true)
}

fn libs() -> Result<Vec<PathBuf>>{
    if let Some(dir) = libs_root(){
        find_files_by_extension(dir,"jar",false)
    }else{
        Ok(vec![])
    }
}

pub struct Kohi{
    dist_path: PathBuf,
    libs: Vec<PathBuf>,
    source_path: PathBuf,
    source_files: Vec<PathBuf>
}

impl Kohi{
    pub fn new() -> Result<Self>{
        let source_root = source_root()?;
        let source_files = source_files(&source_root)?;
        if source_files.len() == 0 {
            bail!(ErrorKind::NoSources(source_root));
        }
        Ok(Kohi{
            dist_path: Path::new("./dist/").to_path_buf(),
            libs: libs()?,
            source_path: source_root,
            source_files: source_files,
        })
    }

    pub fn compile<I: Into<Option<String>>>(self,target_version: I) -> Result<Self>{
        let classpath = std::env::join_paths(&self.libs).unwrap();

        if !self.dist_path.exists(){
            std::fs::create_dir_all(&self.dist_path)?;
        }else{
            if !self.dist_path.is_dir(){
                bail!(ErrorKind::DistNotDir(self.dist_path));
            }
        }

        let mut cmd = Command::new("javac");

        if let Some(target_version) = target_version.into(){
            cmd.arg("-source").arg(target_version.clone()).arg("-target").arg(target_version);
        }

        let status = cmd
            .arg("-d")
            .arg(&self.dist_path)
            .arg("-cp")
            .arg(classpath)
            .arg("-sourcepath")
            .arg(&self.source_path)
            .args(self.source_files.as_slice())
            .status()
            .chain_err(|| ErrorKind::ForkFailure("javac"))?;

        if status.success(){
            Ok(self)
        }else{
            bail!(ErrorKind::ExitFailure("javac",status))
        }
    }

    pub fn run(self, run_class: String) -> Result<Self>{
        //blah.class -> blah
        let run_class = run_class.trim_right_matches(".class");

        let classpath = std::env::join_paths(std::iter::once(&self.dist_path).chain(&self.libs)).unwrap();

        let main = self.find_class(run_class).expect("Couldn't locate the class to run");

        let status = Command::new("java")
                          .arg("-cp")
                          .arg(classpath)
                          .arg(main)
                          .status()
                          .chain_err(|| ErrorKind::ForkFailure("java"))?;

        if status.success(){
            Ok(self)
        }else{
            bail!(ErrorKind::ExitFailure("java",status))
        }
    }

    pub fn package(self, jar_name: &str, entry_point: Option<&str>) -> Result<Self>{
        let mut cmd = Command::new("jar");
        if let Some(entry_point) = entry_point{
            cmd.arg("-cfe")
                .arg(jar_name)
                .arg(entry_point);
        }else{
            cmd.arg("-cf")
                .arg(jar_name);
        }

        let status = cmd
            .arg("-C")
            .arg("dist")
            .args(class_files()?.as_slice())
            .status()
            .chain_err(|| ErrorKind::ForkFailure("jar"))?;

        if status.success(){
            Ok(self)
        }else{
            bail!(ErrorKind::ExitFailure("jar",status))
        }
    }

    fn find_class(&self,class: &str) -> Option<String>{

        let class = class.to_lowercase();
        let mut class_name: Vec<_> = class.split(".").map(ToOwned::to_owned).collect();

        //kinda hacky, but this means we don't have to continuously strip off the dist prefix in the loop
        class_name.insert(0,"dist".to_owned());

        //also a hack to avoid removing the ".class" from the last component constantly
        let len = class_name.len();
        class_name[len-1].push_str(".class");

        let path = find_in_dirs(self.dist_path.as_path(),&mut |entry|{
            let path = entry.path();
            {
                let components = path.components().filter_map(|comp|{
                    use std::path::Component;
                    match comp{
                        Component::Normal(str) => Some(str),
                        _ => None
                    }
                });

                for (a,b) in components.zip(class_name.iter()){
                    if let Some(a) = a.to_str().map(str::to_lowercase){
                        if &a == b{
                            continue
                        }else{
                            return None
                        }
                    }else{
                        return None
                    }
                }
            }
            Some(path)
        }).expect("IO Error while finding class file");

        if let Some(path) = path{
            let mut path = path.strip_prefix(self.dist_path.as_path()).expect("Found something outside of ./dist/ in ./dist/ ???").to_path_buf();
            path.set_extension("");

            let path: Vec<_> = path.iter().flat_map(|s| s.to_str()).map(|s| s.to_owned()).collect();
            let path = path.join(".");

            let path_as_class = path.trim_left_matches(".");
            Some(path_as_class.to_owned())
        }else{
            None
        }
    }
}<|endoftext|>


<commit_before>//! Crate `ruma_events` contains serializable types for the events in the [Matrix](https://matrix.org)
//! specification that can be shared by client and server code.
//!
//! All data exchanged over Matrix is expressed as an event.
//! Different event types represent different actions, such as joining a room or sending a message.
//! Events are stored and transmitted as simple JSON structures.
//! While anyone can create a new event type for their own purposes, the Matrix specification
//! defines a number of event types which are considered core to the protocol, and Matrix clients
//! and servers must understand their semantics.
//! ruma-events contains Rust types for each of the event types defined by the specification and
//! facilities for extending the event system for custom event types.
//!
//! # Event types
//!
//! ruma-events includes a Rust enum called `EventType`, which provides a simple enumeration of
//! all the event types defined by the Matrix specification. Matrix event types are serialized to
//! JSON strings in [reverse domain name
//! notation](https://en.wikipedia.org/wiki/Reverse_domain_name_notation), although the core event
//! types all use the special "m" TLD, e.g. *m.room.message*.
//! `EventType` also includes a variant called `Custom`, which is a catch-all that stores a string
//! containing the name of any event type that isn't part of the specification.
//! `EventType` is used throughout ruma-events to identify and differentiate between events of
//! different types.
//!
//! # Event kinds
//!
//! Matrix defines three "kinds" of events:
//!
//! 1.  **Events**, which are arbitrary JSON structures that have two required keys:
//!     *   `type`, which specifies the event's type
//!     *   `content`, which is a JSON object containing the "payload" of the event
//! 2.  **Room events**, which are a superset of events and represent actions that occurred within
//!     the context of a Matrix room.
//!     They have at least the following additional keys:
//!     *   `event_id`, which is a unique identifier for the event
//!     *   `room_id`, which is a unique identifier for the room in which the event occurred
//!     *   `sender`, which is the unique identifier of the Matrix user who created the event
//!     *   Optionally, `unsigned`, which is a JSON object containing arbitrary additional metadata
//!     that is not digitally signed by Matrix homeservers.
//! 3.  **State events**, which are a superset of room events and represent persistent state
//!     specific to a room, such as the room's member list or topic.
//!     Within a single room, state events of the same type and with the same "state key" will
//!     effectively "replace" the previous one, updating the room's state.
//!     They have at least the following additional keys:
//!     *   `state_key`, a string which serves as a sort of "sub-type."
//!         The state key allows a room to persist multiple state events of the same type.
//!         You can think of a room's state events as being a `BTreeMap` where the keys are the tuple
//!         `(event_type, state_key)`.
//!     *   Optionally, `prev_content`, a JSON object containing the `content` object from the
//!     previous event of the given `(event_type, state_key)` tuple in the given room.
//!
//! ruma-events represents these three event kinds as traits, allowing any Rust type to serve as a
//! Matrix event so long as it upholds the contract expected of its kind.
//!
//! # Core event types
//!
//! ruma-events includes Rust types for every one of the event types in the Matrix specification.
//! To better organize the crate, these types live in separate modules with a hierarchy that
//! matches the reverse domain name notation of the event type.
//! For example, the *m.room.message* event lives at `ruma_events::room::message::MessageEvent`.
//! Each type's module also contains a Rust type for that event type's `content` field, and any
//! other supporting types required by the event's other fields.
//!
//! # Custom event types
//!
//! Although any Rust type that implements `Event`, `RoomEvent`, or `StateEvent` can serve as a
//! Matrix event type, ruma-events also includes a few convenience types for representing events
//! that are not covered by the spec and not otherwise known by the application.
//! `CustomEvent`, `CustomRoomEvent`, and `CustomStateEvent` are simple implementations of their
//! respective event traits whose `content` field is simply a `serde_json::Value` value, which
//! represents arbitrary JSON.
//!
//! # Serialization and deserialization
//!
//! All concrete event types in ruma-events can be serialized via the `Serialize` trait from
//! [serde](https://serde.rs/) and can be deserialized from as `EventJson<EventType>`. In order to
//! handle incoming data that may not conform to `ruma-events`' strict definitions of event
//! structures, deserialization will return `EventJson::Err` on error. This error covers both
//! structurally invalid JSON data as well as structurally valid JSON that doesn't fulfill
//! additional constraints the matrix specification defines for some event types. The error exposes
//! the deserialized `serde_json::Value` so that developers can still work with the received
//! event data. This makes it possible to deserialize a collection of events without the entire
//! collection failing to deserialize due to a single invalid event. The "content" type for each
//! event also implements `Serialize` and either `TryFromRaw` (enabling usage as
//! `EventJson<ContentType>` for dedicated content types) or `Deserialize` (when the content is a
//! type alias), allowing content to be converted to and from JSON indepedently of the surrounding
//! event structure, if needed.
//!
//! # Collections
//!
//! With the trait-based approach to events, it's easy to write generic collection types like
//! `Vec<Box<R: RoomEvent>>`.
//! However, there are APIs in the Matrix specification that involve heterogeneous collections of
//! events, i.e. a list of events of different event types.
//! Because Rust does not have a facility for arrays, vectors, or slices containing multiple
//! concrete types, ruma-events provides special collection types for this purpose.
//! The collection types are enums which effectively "wrap" each possible event type of a
//! particular event "kind."
//!
//! Because of the hierarchical nature of event kinds in Matrix, these collection types are divied
//! into two modules, `ruma_events::collections::all` and `ruma_events::collections::only`.
//! The "all" versions include every event type that implements the relevant event trait as well as
//! more specific event traits.
//! The "only" versions include only the event types that implement "at most" the relevant event
//! trait.
//!
//! For example, the `ruma_events::collections::all::Event` enum includes *m.room.message*, because
//! that event type is both an event and a room event.
//! However, the `ruma_events::collections::only::Event` enum does *not* include *m.room.message*,
//! because *m.room.message* implements a *more specific* event trait than `Event`.

#![recursion_limit = "1024"]
#![warn(missing_debug_implementations, missing_docs, rust_2018_idioms)]
// Since we support Rust 1.36.0, we can't apply this suggestion yet
#![allow(clippy::use_self)]

use std::{fmt::Debug, time::SystemTime};

use js_int::Int;
use ruma_identifiers::{EventId, RoomId, UserId};
use serde::{Deserialize, Serialize};

use self::room::redaction::RedactionEvent;

pub use self::{
    custom::{CustomEvent, CustomRoomEvent, CustomStateEvent},
    empty::Empty,
};

#[macro_use]
mod macros;

mod algorithm;
mod empty;
mod error;
mod event_type;
mod from_raw;
mod json;
#[doc(hidden)] // only public for external tests
pub mod util;

// Hack to allow both ruma-events itself and external crates (or tests) to use procedural macros
// that expect `ruma_events` to exist in the prelude.
extern crate self as ruma_events;

pub mod call;
pub mod custom;
/// Enums for heterogeneous collections of events.
pub mod collections {
    pub mod all;
    pub mod only;

    mod raw {
        pub mod all;
        pub mod only;
    }
}
pub mod direct;
pub mod dummy;
pub mod forwarded_room_key;
pub mod fully_read;
pub mod ignored_user_list;
pub mod key;
pub mod presence;
pub mod push_rules;
pub mod receipt;
pub mod room;
pub mod room_key;
pub mod room_key_request;
pub mod sticker;
pub mod stripped;
pub mod tag;
pub mod to_device;
pub mod typing;

pub use self::{
    algorithm::Algorithm,
    error::{FromStrError, InvalidEvent, InvalidInput},
    event_type::EventType,
    from_raw::{FromRaw, TryFromRaw},
    json::EventJson,
};

/// A basic event.
pub trait Event: Debug + Serialize + Sized + TryFromRaw {
    /// The type of this event's `content` field.
    type Content: Debug + Serialize;

    /// The event's content.
    fn content(&self) -> &Self::Content;

    /// The type of the event.
    fn event_type(&self) -> EventType;
}

/// An event within the context of a room.
pub trait RoomEvent: Event {
    /// The unique identifier for the event.
    fn event_id(&self) -> &EventId;

    /// Time on originating homeserver when this event was sent.
    fn origin_server_ts(&self) -> SystemTime;

    /// The unique identifier for the room associated with this event.
    ///
    /// This can be `None` if the event came from a context where there is
    /// no ambiguity which room it belongs to, like a `/sync` response for example.
    fn room_id(&self) -> Option<&RoomId>;

    /// The unique identifier for the user who sent this event.
    fn sender(&self) -> &UserId;

    /// Additional key-value pairs not signed by the homeserver.
    fn unsigned(&self) -> &UnsignedData;
}

/// An event that describes persistent state about a room.
pub trait StateEvent: RoomEvent {
    /// The previous content for this state key, if any.
    fn prev_content(&self) -> Option<&Self::Content>;

    /// A key that determines which piece of room state the event represents.
    fn state_key(&self) -> &str;
}

/// Extra information about an event that is not incorporated into the event's
/// hash.
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
pub struct UnsignedData {
    /// The time in milliseconds that has elapsed since the event was sent. This
    /// field is generated by the local homeserver, and may be incorrect if the
    /// local time on at least one of the two servers is out of sync, which can
    /// cause the age to either be negative or greater than it actually is.
    #[serde(skip_serializing_if = "Option::is_none")]
    age: Option<Int>,
    /// The event that redacted this event, if any.
    #[serde(skip_serializing_if = "Option::is_none")]
    redacted_because: Option<EventJson<RedactionEvent>>,
    /// The client-supplied transaction ID, if the client being given the event
    /// is the same one which sent it.
    #[serde(skip_serializing_if = "Option::is_none")]
    transaction_id: Option<String>,
}

impl UnsignedData {
    /// Whether this unsigned data is empty (all fields are `None`).
    ///
    /// This method is used to determine whether to skip serializing the
    /// `unsigned` field in room events. Do not use it to determine whether
    /// an incoming `unsigned` field was present - it could still have been
    /// present but contained none of the known fields.
    pub fn is_empty(&self) -> bool {
        self.age.is_none() && self.redacted_because.is_none() && self.transaction_id.is_none()
    }
}
<commit_msg>Make UnsignedData's fields public<commit_after>//! Crate `ruma_events` contains serializable types for the events in the [Matrix](https://matrix.org)
//! specification that can be shared by client and server code.
//!
//! All data exchanged over Matrix is expressed as an event.
//! Different event types represent different actions, such as joining a room or sending a message.
//! Events are stored and transmitted as simple JSON structures.
//! While anyone can create a new event type for their own purposes, the Matrix specification
//! defines a number of event types which are considered core to the protocol, and Matrix clients
//! and servers must understand their semantics.
//! ruma-events contains Rust types for each of the event types defined by the specification and
//! facilities for extending the event system for custom event types.
//!
//! # Event types
//!
//! ruma-events includes a Rust enum called `EventType`, which provides a simple enumeration of
//! all the event types defined by the Matrix specification. Matrix event types are serialized to
//! JSON strings in [reverse domain name
//! notation](https://en.wikipedia.org/wiki/Reverse_domain_name_notation), although the core event
//! types all use the special "m" TLD, e.g. *m.room.message*.
//! `EventType` also includes a variant called `Custom`, which is a catch-all that stores a string
//! containing the name of any event type that isn't part of the specification.
//! `EventType` is used throughout ruma-events to identify and differentiate between events of
//! different types.
//!
//! # Event kinds
//!
//! Matrix defines three "kinds" of events:
//!
//! 1.  **Events**, which are arbitrary JSON structures that have two required keys:
//!     *   `type`, which specifies the event's type
//!     *   `content`, which is a JSON object containing the "payload" of the event
//! 2.  **Room events**, which are a superset of events and represent actions that occurred within
//!     the context of a Matrix room.
//!     They have at least the following additional keys:
//!     *   `event_id`, which is a unique identifier for the event
//!     *   `room_id`, which is a unique identifier for the room in which the event occurred
//!     *   `sender`, which is the unique identifier of the Matrix user who created the event
//!     *   Optionally, `unsigned`, which is a JSON object containing arbitrary additional metadata
//!     that is not digitally signed by Matrix homeservers.
//! 3.  **State events**, which are a superset of room events and represent persistent state
//!     specific to a room, such as the room's member list or topic.
//!     Within a single room, state events of the same type and with the same "state key" will
//!     effectively "replace" the previous one, updating the room's state.
//!     They have at least the following additional keys:
//!     *   `state_key`, a string which serves as a sort of "sub-type."
//!         The state key allows a room to persist multiple state events of the same type.
//!         You can think of a room's state events as being a `BTreeMap` where the keys are the tuple
//!         `(event_type, state_key)`.
//!     *   Optionally, `prev_content`, a JSON object containing the `content` object from the
//!     previous event of the given `(event_type, state_key)` tuple in the given room.
//!
//! ruma-events represents these three event kinds as traits, allowing any Rust type to serve as a
//! Matrix event so long as it upholds the contract expected of its kind.
//!
//! # Core event types
//!
//! ruma-events includes Rust types for every one of the event types in the Matrix specification.
//! To better organize the crate, these types live in separate modules with a hierarchy that
//! matches the reverse domain name notation of the event type.
//! For example, the *m.room.message* event lives at `ruma_events::room::message::MessageEvent`.
//! Each type's module also contains a Rust type for that event type's `content` field, and any
//! other supporting types required by the event's other fields.
//!
//! # Custom event types
//!
//! Although any Rust type that implements `Event`, `RoomEvent`, or `StateEvent` can serve as a
//! Matrix event type, ruma-events also includes a few convenience types for representing events
//! that are not covered by the spec and not otherwise known by the application.
//! `CustomEvent`, `CustomRoomEvent`, and `CustomStateEvent` are simple implementations of their
//! respective event traits whose `content` field is simply a `serde_json::Value` value, which
//! represents arbitrary JSON.
//!
//! # Serialization and deserialization
//!
//! All concrete event types in ruma-events can be serialized via the `Serialize` trait from
//! [serde](https://serde.rs/) and can be deserialized from as `EventJson<EventType>`. In order to
//! handle incoming data that may not conform to `ruma-events`' strict definitions of event
//! structures, deserialization will return `EventJson::Err` on error. This error covers both
//! structurally invalid JSON data as well as structurally valid JSON that doesn't fulfill
//! additional constraints the matrix specification defines for some event types. The error exposes
//! the deserialized `serde_json::Value` so that developers can still work with the received
//! event data. This makes it possible to deserialize a collection of events without the entire
//! collection failing to deserialize due to a single invalid event. The "content" type for each
//! event also implements `Serialize` and either `TryFromRaw` (enabling usage as
//! `EventJson<ContentType>` for dedicated content types) or `Deserialize` (when the content is a
//! type alias), allowing content to be converted to and from JSON indepedently of the surrounding
//! event structure, if needed.
//!
//! # Collections
//!
//! With the trait-based approach to events, it's easy to write generic collection types like
//! `Vec<Box<R: RoomEvent>>`.
//! However, there are APIs in the Matrix specification that involve heterogeneous collections of
//! events, i.e. a list of events of different event types.
//! Because Rust does not have a facility for arrays, vectors, or slices containing multiple
//! concrete types, ruma-events provides special collection types for this purpose.
//! The collection types are enums which effectively "wrap" each possible event type of a
//! particular event "kind."
//!
//! Because of the hierarchical nature of event kinds in Matrix, these collection types are divied
//! into two modules, `ruma_events::collections::all` and `ruma_events::collections::only`.
//! The "all" versions include every event type that implements the relevant event trait as well as
//! more specific event traits.
//! The "only" versions include only the event types that implement "at most" the relevant event
//! trait.
//!
//! For example, the `ruma_events::collections::all::Event` enum includes *m.room.message*, because
//! that event type is both an event and a room event.
//! However, the `ruma_events::collections::only::Event` enum does *not* include *m.room.message*,
//! because *m.room.message* implements a *more specific* event trait than `Event`.

#![recursion_limit = "1024"]
#![warn(missing_debug_implementations, missing_docs, rust_2018_idioms)]
// Since we support Rust 1.36.0, we can't apply this suggestion yet
#![allow(clippy::use_self)]

use std::{fmt::Debug, time::SystemTime};

use js_int::Int;
use ruma_identifiers::{EventId, RoomId, UserId};
use serde::{Deserialize, Serialize};

use self::room::redaction::RedactionEvent;

pub use self::{
    custom::{CustomEvent, CustomRoomEvent, CustomStateEvent},
    empty::Empty,
};

#[macro_use]
mod macros;

mod algorithm;
mod empty;
mod error;
mod event_type;
mod from_raw;
mod json;
#[doc(hidden)] // only public for external tests
pub mod util;

// Hack to allow both ruma-events itself and external crates (or tests) to use procedural macros
// that expect `ruma_events` to exist in the prelude.
extern crate self as ruma_events;

pub mod call;
pub mod custom;
/// Enums for heterogeneous collections of events.
pub mod collections {
    pub mod all;
    pub mod only;

    mod raw {
        pub mod all;
        pub mod only;
    }
}
pub mod direct;
pub mod dummy;
pub mod forwarded_room_key;
pub mod fully_read;
pub mod ignored_user_list;
pub mod key;
pub mod presence;
pub mod push_rules;
pub mod receipt;
pub mod room;
pub mod room_key;
pub mod room_key_request;
pub mod sticker;
pub mod stripped;
pub mod tag;
pub mod to_device;
pub mod typing;

pub use self::{
    algorithm::Algorithm,
    error::{FromStrError, InvalidEvent, InvalidInput},
    event_type::EventType,
    from_raw::{FromRaw, TryFromRaw},
    json::EventJson,
};

/// A basic event.
pub trait Event: Debug + Serialize + Sized + TryFromRaw {
    /// The type of this event's `content` field.
    type Content: Debug + Serialize;

    /// The event's content.
    fn content(&self) -> &Self::Content;

    /// The type of the event.
    fn event_type(&self) -> EventType;
}

/// An event within the context of a room.
pub trait RoomEvent: Event {
    /// The unique identifier for the event.
    fn event_id(&self) -> &EventId;

    /// Time on originating homeserver when this event was sent.
    fn origin_server_ts(&self) -> SystemTime;

    /// The unique identifier for the room associated with this event.
    ///
    /// This can be `None` if the event came from a context where there is
    /// no ambiguity which room it belongs to, like a `/sync` response for example.
    fn room_id(&self) -> Option<&RoomId>;

    /// The unique identifier for the user who sent this event.
    fn sender(&self) -> &UserId;

    /// Additional key-value pairs not signed by the homeserver.
    fn unsigned(&self) -> &UnsignedData;
}

/// An event that describes persistent state about a room.
pub trait StateEvent: RoomEvent {
    /// The previous content for this state key, if any.
    fn prev_content(&self) -> Option<&Self::Content>;

    /// A key that determines which piece of room state the event represents.
    fn state_key(&self) -> &str;
}

/// Extra information about an event that is not incorporated into the event's
/// hash.
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
pub struct UnsignedData {
    /// The time in milliseconds that has elapsed since the event was sent. This
    /// field is generated by the local homeserver, and may be incorrect if the
    /// local time on at least one of the two servers is out of sync, which can
    /// cause the age to either be negative or greater than it actually is.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub age: Option<Int>,
    /// The event that redacted this event, if any.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub redacted_because: Option<EventJson<RedactionEvent>>,
    /// The client-supplied transaction ID, if the client being given the event
    /// is the same one which sent it.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub transaction_id: Option<String>,
}

impl UnsignedData {
    /// Whether this unsigned data is empty (all fields are `None`).
    ///
    /// This method is used to determine whether to skip serializing the
    /// `unsigned` field in room events. Do not use it to determine whether
    /// an incoming `unsigned` field was present - it could still have been
    /// present but contained none of the known fields.
    pub fn is_empty(&self) -> bool {
        self.age.is_none() && self.redacted_because.is_none() && self.transaction_id.is_none()
    }
}
<|endoftext|>


<commit_before>extern crate libc;

mod context;
mod ffi;
mod measure;
mod measures;
mod node;

pub use ffi::Align;
pub use ffi::Dimensions;
pub use ffi::Direction;
pub use ffi::Edge;
pub use ffi::ExperimentalFeature;
pub use ffi::FlexDirection;
pub use ffi::FlexWrap;
pub use ffi::JustifyContent;
pub use ffi::LogLevel;
pub use ffi::MeasureMode;
pub use ffi::Overflow;
pub use ffi::PositionType;
pub use ffi::PrintOptions;
pub use ffi::Size;

pub use context::Context;
pub use measure::measure;
pub use measures::Measures;
pub use node::Node;
<commit_msg>chore(Node): expose yoga node as RawNode<commit_after>extern crate libc;

mod context;
mod ffi;
mod measure;
mod measures;
mod node;

pub use ffi::Align;
pub use ffi::Dimensions;
pub use ffi::Direction;
pub use ffi::Edge;
pub use ffi::ExperimentalFeature;
pub use ffi::FlexDirection;
pub use ffi::FlexWrap;
pub use ffi::JustifyContent;
pub use ffi::LogLevel;
pub use ffi::MeasureMode;
pub use ffi::Overflow;
pub use ffi::PositionType;
pub use ffi::PrintOptions;
pub use ffi::Size;

pub use ffi::Node as RawNode;

pub use context::Context;
pub use measure::measure;
pub use measures::Measures;
pub use node::Node;
<|endoftext|>


<commit_before>#![doc(html_root_url = "https://docs.rs/itoa/0.4.3")]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(
    feature = "cargo-clippy",
    allow(cast_lossless, unreadable_literal)
)]

#[cfg(feature = "i128")]
mod udiv128;

#[cfg(feature = "std")]
use std::{fmt, io, mem, ptr, slice, str};

#[cfg(not(feature = "std"))]
use core::{fmt, mem, ptr, slice, str};

/// Write integer to an `io::Write`.
#[cfg(feature = "std")]
#[inline]
pub fn write<W: io::Write, V: Integer>(mut wr: W, value: V) -> io::Result<usize> {
    let mut buf = Buffer::new();
    let s = buf.format(value);
    try!(wr.write_all(s.as_bytes()));
    Ok(s.len())
}

/// Write integer to an `fmt::Write`.
#[inline]
pub fn fmt<W: fmt::Write, V: Integer>(mut wr: W, value: V) -> fmt::Result {
    let mut buf = Buffer::new();
    wr.write_str(buf.format(value))
}

/// A safe API for formatting integers to text.
///
/// # Example
///
/// ```
/// let mut buffer = itoa::Buffer::new();
/// let printed = buffer.format(1234);
/// assert_eq!(printed, "1234");
/// ```
#[derive(Copy)]
pub struct Buffer {
    bytes: [u8; I128_MAX_LEN],
}

impl Default for Buffer {
    #[inline]
    fn default() -> Buffer {
        Buffer::new()
    }
}

impl Clone for Buffer {
    #[inline]
    fn clone(&self) -> Self {
        Buffer::new()
    }
}

impl Buffer {
    /// This is a cheap operation; you don't need to worry about reusing buffers
    /// for efficiency.
    #[inline]
    pub fn new() -> Buffer {
        Buffer {
            bytes: unsafe { mem::uninitialized() },
        }
    }

    /// Print an integer into this buffer and return a reference to its string representation
    /// within the buffer.
    pub fn format(&mut self, i: I) -> &str {
        i.write(self)
    }
}

// Seal to prevent downstream implementations of the Integer trait.
mod private {
    pub trait Sealed {}
}

/// An integer that can be formatted by `itoa::write` and `itoa::fmt`.
///
/// This trait is sealed and cannot be implemented for types outside of itoa.
pub trait Integer: private::Sealed {
    // Not public API.
    #[doc(hidden)]
    fn write<'a>(self, buf: &'a mut Buffer) -> &'a str;
}

trait IntegerPrivate {
    fn write_to(self, buf: &mut B) -> &[u8];
}

const DEC_DIGITS_LUT: &'static [u8] = b"\
      0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

// Adaptation of the original implementation at
// https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
macro_rules! impl_IntegerCommon {
    ($max_len:expr, $t:ident) => {
        impl Integer for $t {
            #[inline]
            fn write<'a>(self, buf: &'a mut Buffer) -> &'a str {
                unsafe {
                    debug_assert!($max_len <= I128_MAX_LEN);
                    let buf = mem::transmute::<&mut [u8; I128_MAX_LEN], &mut [u8; $max_len]>(
                        &mut buf.bytes,
                    );
                    let bytes = self.write_to(buf);
                    str::from_utf8_unchecked(bytes)
                }
            }
        }

        impl private::Sealed for $t {}
    };
}

macro_rules! impl_Integer {
    ($($max_len:expr => $t:ident),* as $conv_fn:ident) => {$(
        impl_IntegerCommon!($max_len, $t);

        impl IntegerPrivate<[u8; $max_len]> for $t {
            #[allow(unused_comparisons)]
            #[inline]
            fn write_to(self, buf: &mut [u8; $max_len]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let mut n = if is_nonnegative {
                    self as $conv_fn
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as $conv_fn)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();
                let lut_ptr = DEC_DIGITS_LUT.as_ptr();

                unsafe {
                    // need at least 16 bits for the 4-characters-at-a-time to work.
                    if mem::size_of::<$t>() >= 2 {
                        // eagerly decode 4 characters at a time
                        while n >= 10000 {
                            let rem = (n % 10000) as isize;
                            n /= 10000;

                            let d1 = (rem / 100) << 1;
                            let d2 = (rem % 100) << 1;
                            curr -= 4;
                            ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                            ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                        }
                    }

                    // if we reach here numbers are <= 9999, so at most 4 chars long
                    let mut n = n as isize; // possibly reduce 64bit math

                    // decode 2 more chars, if > 2 chars
                    if n >= 100 {
                        let d1 = (n % 100) << 1;
                        n /= 100;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    // decode last 1 or 2 chars
                    if n < 10 {
                        curr -= 1;
                        *buf_ptr.offset(curr) = (n as u8) + b'0';
                    } else {
                        let d1 = n << 1;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }
                }

                let len = buf.len() - curr as usize;
                unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) }
            }
        }
    )*};
}

const I8_MAX_LEN: usize = 4;
const U8_MAX_LEN: usize = 3;
const I16_MAX_LEN: usize = 6;
const U16_MAX_LEN: usize = 5;
const I32_MAX_LEN: usize = 11;
const U32_MAX_LEN: usize = 10;
const I64_MAX_LEN: usize = 20;
const U64_MAX_LEN: usize = 20;

impl_Integer!(
    I8_MAX_LEN => i8,
    U8_MAX_LEN => u8,
    I16_MAX_LEN => i16,
    U16_MAX_LEN => u16,
    I32_MAX_LEN => i32,
    U32_MAX_LEN => u32
    as u32);

impl_Integer!(I64_MAX_LEN => i64, U64_MAX_LEN => u64 as u64);

#[cfg(target_pointer_width = "16")]
impl_Integer!(I16_MAX_LEN => isize, U16_MAX_LEN => usize as u16);

#[cfg(target_pointer_width = "32")]
impl_Integer!(I32_MAX_LEN => isize, U32_MAX_LEN => usize as u32);

#[cfg(target_pointer_width = "64")]
impl_Integer!(I64_MAX_LEN => isize, U64_MAX_LEN => usize as u64);

#[cfg(all(feature = "i128"))]
macro_rules! impl_Integer128 {
    ($($max_len:expr => $t:ident),*) => {$(
        impl_IntegerCommon!($max_len, $t);

        impl IntegerPrivate<[u8; $max_len]> for $t {
            #[allow(unused_comparisons)]
            #[inline]
            fn write_to(self, buf: &mut [u8; $max_len]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let n = if is_nonnegative {
                    self as u128
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as u128)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();

                unsafe {
                    // Divide by 10^19 which is the highest power less than 2^64.
                    let (n, rem) = udiv128::udivmod_1e19(n);
                    let buf1 = buf_ptr.offset(curr - U64_MAX_LEN as isize) as *mut [u8; U64_MAX_LEN];
                    curr -= rem.write_to(&mut *buf1).len() as isize;

                    if n != 0 {
                        // Memset the base10 leading zeros of rem.
                        let target = buf.len() as isize - 19;
                        ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                        curr = target;

                        // Divide by 10^19 again.
                        let (n, rem) = udiv128::udivmod_1e19(n);
                        let buf2 = buf_ptr.offset(curr - U64_MAX_LEN as isize) as *mut [u8; U64_MAX_LEN];
                        curr -= rem.write_to(&mut *buf2).len() as isize;

                        if n != 0 {
                            // Memset the leading zeros.
                            let target = buf.len() as isize - 38;
                            ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                            curr = target;

                            // There is at most one digit left
                            // because u128::max / 10^19 / 10^19 is 3.
                            curr -= 1;
                            *buf_ptr.offset(curr) = (n as u8) + b'0';
                        }
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }

                    let len = buf.len() - curr as usize;
                    slice::from_raw_parts(buf_ptr.offset(curr), len)
                }
            }
        }
    )*};
}

#[cfg(all(feature = "i128"))]
const U128_MAX_LEN: usize = 39;
const I128_MAX_LEN: usize = 40;

#[cfg(all(feature = "i128"))]
impl_Integer128!(I128_MAX_LEN => i128, U128_MAX_LEN => u128);
<commit_msg>Copy part of readme to crate-level doc<commit_after>//! This crate provides fast functions for printing integer primitives to an
//! [`io::Write`] or a [`fmt::Write`]. The implementation comes straight from
//! [libcore] but avoids the performance penalty of going through
//! [`fmt::Formatter`].
//!
//! See also [`dtoa`] for printing floating point primitives.
//!
//! [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
//! [`fmt::Write`]: https://doc.rust-lang.org/core/fmt/trait.Write.html
//! [libcore]: https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L201-L254
//! [`fmt::Formatter`]: https://doc.rust-lang.org/std/fmt/struct.Formatter.html
//! [`dtoa`]: https://github.com/dtolnay/dtoa
//!
//!

//!
//! # Performance (lower is better)
//!
//! ![performance](https://raw.githubusercontent.com/dtolnay/itoa/master/performance.png)
//!
//!

//!
//! # Examples
//!
//! ```edition2018
//! use std::{fmt, io};
//!
//! fn demo_itoa_write() -> io::Result<()> {
//!     // Write to a vector or other io::Write.
//!     let mut buf = Vec::new();
//!     itoa::write(&mut buf, 128u64)?;
//!     println!("{:?}", buf);
//!
//!     // Write to a stack buffer.
//!     let mut bytes = [0u8; 20];
//!     let n = itoa::write(&mut bytes[..], 128u64)?;
//!     println!("{:?}", &bytes[..n]);
//!
//!     Ok(())
//! }
//!
//! fn demo_itoa_fmt() -> fmt::Result {
//!     // Write to a string.
//!     let mut s = String::new();
//!     itoa::fmt(&mut s, 128u64)?;
//!     println!("{}", s);
//!
//!     Ok(())
//! }
//! ```

#![doc(html_root_url = "https://docs.rs/itoa/0.4.3")]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(
    feature = "cargo-clippy",
    allow(cast_lossless, unreadable_literal)
)]

#[cfg(feature = "i128")]
mod udiv128;

#[cfg(feature = "std")]
use std::{fmt, io, mem, ptr, slice, str};

#[cfg(not(feature = "std"))]
use core::{fmt, mem, ptr, slice, str};

/// Write integer to an `io::Write`.
#[cfg(feature = "std")]
#[inline]
pub fn write<W: io::Write, V: Integer>(mut wr: W, value: V) -> io::Result<usize> {
    let mut buf = Buffer::new();
    let s = buf.format(value);
    try!(wr.write_all(s.as_bytes()));
    Ok(s.len())
}

/// Write integer to an `fmt::Write`.
#[inline]
pub fn fmt<W: fmt::Write, V: Integer>(mut wr: W, value: V) -> fmt::Result {
    let mut buf = Buffer::new();
    wr.write_str(buf.format(value))
}

/// A safe API for formatting integers to text.
///
/// # Example
///
/// ```
/// let mut buffer = itoa::Buffer::new();
/// let printed = buffer.format(1234);
/// assert_eq!(printed, "1234");
/// ```
#[derive(Copy)]
pub struct Buffer {
    bytes: [u8; I128_MAX_LEN],
}

impl Default for Buffer {
    #[inline]
    fn default() -> Buffer {
        Buffer::new()
    }
}

impl Clone for Buffer {
    #[inline]
    fn clone(&self) -> Self {
        Buffer::new()
    }
}

impl Buffer {
    /// This is a cheap operation; you don't need to worry about reusing buffers
    /// for efficiency.
    #[inline]
    pub fn new() -> Buffer {
        Buffer {
            bytes: unsafe { mem::uninitialized() },
        }
    }

    /// Print an integer into this buffer and return a reference to its string representation
    /// within the buffer.
    pub fn format(&mut self, i: I) -> &str {
        i.write(self)
    }
}

// Seal to prevent downstream implementations of the Integer trait.
mod private {
    pub trait Sealed {}
}

/// An integer that can be formatted by `itoa::write` and `itoa::fmt`.
///
/// This trait is sealed and cannot be implemented for types outside of itoa.
pub trait Integer: private::Sealed {
    // Not public API.
    #[doc(hidden)]
    fn write<'a>(self, buf: &'a mut Buffer) -> &'a str;
}

trait IntegerPrivate {
    fn write_to(self, buf: &mut B) -> &[u8];
}

const DEC_DIGITS_LUT: &'static [u8] = b"\
      0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

// Adaptation of the original implementation at
// https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
macro_rules! impl_IntegerCommon {
    ($max_len:expr, $t:ident) => {
        impl Integer for $t {
            #[inline]
            fn write<'a>(self, buf: &'a mut Buffer) -> &'a str {
                unsafe {
                    debug_assert!($max_len <= I128_MAX_LEN);
                    let buf = mem::transmute::<&mut [u8; I128_MAX_LEN], &mut [u8; $max_len]>(
                        &mut buf.bytes,
                    );
                    let bytes = self.write_to(buf);
                    str::from_utf8_unchecked(bytes)
                }
            }
        }

        impl private::Sealed for $t {}
    };
}

macro_rules! impl_Integer {
    ($($max_len:expr => $t:ident),* as $conv_fn:ident) => {$(
        impl_IntegerCommon!($max_len, $t);

        impl IntegerPrivate<[u8; $max_len]> for $t {
            #[allow(unused_comparisons)]
            #[inline]
            fn write_to(self, buf: &mut [u8; $max_len]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let mut n = if is_nonnegative {
                    self as $conv_fn
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as $conv_fn)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();
                let lut_ptr = DEC_DIGITS_LUT.as_ptr();

                unsafe {
                    // need at least 16 bits for the 4-characters-at-a-time to work.
                    if mem::size_of::<$t>() >= 2 {
                        // eagerly decode 4 characters at a time
                        while n >= 10000 {
                            let rem = (n % 10000) as isize;
                            n /= 10000;

                            let d1 = (rem / 100) << 1;
                            let d2 = (rem % 100) << 1;
                            curr -= 4;
                            ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                            ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                        }
                    }

                    // if we reach here numbers are <= 9999, so at most 4 chars long
                    let mut n = n as isize; // possibly reduce 64bit math

                    // decode 2 more chars, if > 2 chars
                    if n >= 100 {
                        let d1 = (n % 100) << 1;
                        n /= 100;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    // decode last 1 or 2 chars
                    if n < 10 {
                        curr -= 1;
                        *buf_ptr.offset(curr) = (n as u8) + b'0';
                    } else {
                        let d1 = n << 1;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }
                }

                let len = buf.len() - curr as usize;
                unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) }
            }
        }
    )*};
}

const I8_MAX_LEN: usize = 4;
const U8_MAX_LEN: usize = 3;
const I16_MAX_LEN: usize = 6;
const U16_MAX_LEN: usize = 5;
const I32_MAX_LEN: usize = 11;
const U32_MAX_LEN: usize = 10;
const I64_MAX_LEN: usize = 20;
const U64_MAX_LEN: usize = 20;

impl_Integer!(
    I8_MAX_LEN => i8,
    U8_MAX_LEN => u8,
    I16_MAX_LEN => i16,
    U16_MAX_LEN => u16,
    I32_MAX_LEN => i32,
    U32_MAX_LEN => u32
    as u32);

impl_Integer!(I64_MAX_LEN => i64, U64_MAX_LEN => u64 as u64);

#[cfg(target_pointer_width = "16")]
impl_Integer!(I16_MAX_LEN => isize, U16_MAX_LEN => usize as u16);

#[cfg(target_pointer_width = "32")]
impl_Integer!(I32_MAX_LEN => isize, U32_MAX_LEN => usize as u32);

#[cfg(target_pointer_width = "64")]
impl_Integer!(I64_MAX_LEN => isize, U64_MAX_LEN => usize as u64);

#[cfg(all(feature = "i128"))]
macro_rules! impl_Integer128 {
    ($($max_len:expr => $t:ident),*) => {$(
        impl_IntegerCommon!($max_len, $t);

        impl IntegerPrivate<[u8; $max_len]> for $t {
            #[allow(unused_comparisons)]
            #[inline]
            fn write_to(self, buf: &mut [u8; $max_len]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let n = if is_nonnegative {
                    self as u128
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as u128)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();

                unsafe {
                    // Divide by 10^19 which is the highest power less than 2^64.
                    let (n, rem) = udiv128::udivmod_1e19(n);
                    let buf1 = buf_ptr.offset(curr - U64_MAX_LEN as isize) as *mut [u8; U64_MAX_LEN];
                    curr -= rem.write_to(&mut *buf1).len() as isize;

                    if n != 0 {
                        // Memset the base10 leading zeros of rem.
                        let target = buf.len() as isize - 19;
                        ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                        curr = target;

                        // Divide by 10^19 again.
                        let (n, rem) = udiv128::udivmod_1e19(n);
                        let buf2 = buf_ptr.offset(curr - U64_MAX_LEN as isize) as *mut [u8; U64_MAX_LEN];
                        curr -= rem.write_to(&mut *buf2).len() as isize;

                        if n != 0 {
                            // Memset the leading zeros.
                            let target = buf.len() as isize - 38;
                            ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                            curr = target;

                            // There is at most one digit left
                            // because u128::max / 10^19 / 10^19 is 3.
                            curr -= 1;
                            *buf_ptr.offset(curr) = (n as u8) + b'0';
                        }
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }

                    let len = buf.len() - curr as usize;
                    slice::from_raw_parts(buf_ptr.offset(curr), len)
                }
            }
        }
    )*};
}

#[cfg(all(feature = "i128"))]
const U128_MAX_LEN: usize = 39;
const I128_MAX_LEN: usize = 40;

#[cfg(all(feature = "i128"))]
impl_Integer128!(I128_MAX_LEN => i128, U128_MAX_LEN => u128);
<|endoftext|>


<commit_before>extern crate libc;

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

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

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

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

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

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

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

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

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

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

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

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


<commit_before>extern crate tokio;
extern crate futures;

#[macro_use]
extern crate log;

use tokio::{server, Service, NewService};
use tokio::io::{Readiness, Transport};
use tokio::proto::pipeline;
use tokio::reactor::ReactorHandle;
use tokio::tcp::TcpStream;
use tokio::util::future::Empty;
use futures::Future;
use std::{io, mem};
use std::net::SocketAddr;

/// Line transport. This is a pretty bare implementation of a Transport that is chunked into
/// individual lines. The job of a transport is twofold:
///
/// 1) take the bytes that arrive on our 'inner' (e.g. socket) and chunk them down into frames as
///    Transport::In.
/// 2) take the frames as Transport::Out to send out and turn them into bytes. This allows for
///    example for combining multiple frames into one TCP send.
///
/// The Service only deals in The magic here is that 'inner' must implement 'Readiness' - this allows it to play with Tokio's
/// reactor.
pub struct Line<T> {
    inner: T,
    read_buffer: Vec<u8>,
    write_buffer: io::Cursor<Vec<u8>>,
}

impl<T> Line<T>
    where T: io::Read + io::Write + Readiness,
{
    pub fn new(inner: T) -> Line<T> {
        Line {
            inner: inner,
            read_buffer: vec![],
            write_buffer: io::Cursor::new(vec![]),
        }
    }
}

impl<T> Readiness for Line<T>
    where T: Readiness
{
    // Our transport is ready for reading whenever our 'inner'.
    fn is_readable(&self) -> bool {
        self.inner.is_readable()
    }

    // And ready for writing whenever inner is. Below we make sure that we always write everything
    // out to 'inner' whenever it is ready, so our writing buf should always be empty when 'inner'
    // is ready for writing and non-empty if it isn't.
    fn is_writable(&self) -> bool {
        let is_writable = self.write_buffer.position() == self.write_buffer.get_ref().len() as u64;

        if !is_writable {
            assert!(!self.inner.is_writable());
        }

        is_writable
    }
}

/// This defines the chunks written to our transport, i.e. the representation
/// that the `Service` deals with. In our case, the received and sent frames
/// are mostly the same (Strings with io::Error as failures), however they
/// could also be different (for example HttpRequest for In and HttpResponse
/// for Out).
pub type Frame = pipeline::Frame<String, io::Error>;

/// This is a bare-metal implementation of a Transport. We define our frames to be String when
/// reading from the wire, that is 'In' and also String when writing to the wire.
impl<T> Transport for Line<T>
    where T: io::Read + io::Write + Readiness
{
    type In = Frame;
    type Out = Frame;

    /// Read a message from the `Transport`
    fn read(&mut self) -> io::Result<Option<Frame>> {
        loop {
            // First, we check if our read buffer contains a new line - if that is the case, we
            // have one new Frame for the Service to consume. We remove the line from the input
            // buffer and this function will get called by Tokio soon again to see if there are
            // more frames available.
            if let Some(n) = self.read_buffer.iter().position(|b| *b == b'\n') {
                let tail = self.read_buffer.split_off(n+1);
                let mut line = mem::replace(&mut self.read_buffer, tail);

                // Remove the new line
                line.truncate(n);

                return String::from_utf8(line)
                    // For pipelined protocols, the message must be a tuple
                    // of the message payload to be sent to the Service and
                    // Option<Sender<T>> where T is the body chunk type.
                    //
                    // To support streaming bodies, the transport could create
                    // a channel pair, include the receiving end in the message
                    // payload and provide the sending end to the pipeline
                    // protocol dispatcher which will then proxy any body chunk
                    // frame to the Sender.
                    .map(|s| Some(pipeline::Frame::Message(s)))
                    .map_err(|_| io::Error::new(io::ErrorKind::Other, "invalid string"));
            }

            // There was no full line in the input buffer - let's see if anything is on our
            // 'inner'.
            match self.inner.read_to_end(&mut self.read_buffer) {
                Ok(0) => {
                    // The other side hang up - this transport is all done.
                    // TODO(sirver): The use case of this is not entirely clear to me.
                    return Ok(Some(pipeline::Frame::Done));
                },
                Ok(_) => {
                    // Some data was read. The next round in the loop will try to parse it into a
                    // line again.
                }
                Err(e) => {
                    // This would block - i.e. there is no data on the socket. We signal Tokio that
                    // there is right now no full frame available. It will try again the next time
                    // our source signals readiness to read.
                    if e.kind() == io::ErrorKind::WouldBlock {
                        return Ok(None);
                    }

                    // Just a regular error - pass upwards for handling.
                    return Err(e)
                }
            }
        }
    }

    /// Write a message to the `Transport`. This turns the frame we get into a byte string and adds
    /// a newline. It then immediately gets flushed out to 'inner'.
    fn write(&mut self, req: Frame) -> io::Result<Option<()>> {
        match req {
            pipeline::Frame::Message(req) => {
                trace!("writing value; val={:?}", req);
                // Our write buffer can only be non-empty if our 'inner' is not ready for writes.
                // But since we signal to Tokio that our Transport is not ready when 'inner' is not
                // ready it should never try to write to us as long as our write buffer is not
                // empty.
                if self.write_buffer.position() < self.write_buffer.get_ref().len() as u64 {
                    return Err(io::Error::new(io::ErrorKind::Other, "transport has pending writes"));
                }

                let mut bytes = req.into_bytes();
                bytes.push(b'\n');

                self.write_buffer = io::Cursor::new(bytes);
                self.flush()
            }
            _ => unimplemented!(),
        }
    }

    /// Flush pending writes to the socket. This tries to write as much as possible of the data we
    /// have in the write buffer to 'inner'. Since this might block - because inner is not ready,
    /// we have to keep track of what we wrote.
    fn flush(&mut self) -> io::Result<Option<()>> {
        trace!("flushing transport");
        loop {
            // Making the borrow checker happy
            let res = {
                let buf = {
                    let pos = self.write_buffer.position() as usize;
                    let buf = &self.write_buffer.get_ref()[pos..];

                    if buf.is_empty() {
                        trace!("transport flushed");
                        return Ok(Some(()));
                    }

                    trace!("writing; remaining={:?}", buf);

                    buf
                };

                self.inner.write(buf)
            };

            match res {
                Ok(mut n) => {
                    n += self.write_buffer.position() as usize;
                    self.write_buffer.set_position(n as u64)
                }
                Err(e) => {
                    if e.kind() == io::ErrorKind::WouldBlock {
                        trace!("transport flush would block");
                        return Ok(None);
                    }

                    trace!("transport flush error; err={:?}", e);
                    return Err(e)
                }
            }
        }
    }
}

/// The Message type with the `Service`. Since the `Line` protocol does not
/// have any streaming bodies, the body component is hard coded to an empty
/// stream.
pub type Message = pipeline::Message<String, Empty<(), io::Error>>;

/// We want to encapsulate `pipeline::Message`. Since the line protocol does
/// not have any streaming bodies, we can make the service be a request &
/// response of type String. `LineService` takes the service supplied to
/// `serve` and adapts it to work with the `proto::pipeline::Server`
/// requirements.
struct LineService<T> {
    inner: T,
}

impl<T> Service for LineService<T>
    where T: Service<Req = String, Resp = String, Error = io::Error>,
{
    type Req = String;
    type Resp = pipeline::Message<String, Empty<(), io::Error>>;
    type Error = io::Error;

    // To make things easier, we are just going to box the future here, however
    // it is possible to not box the future and refer to `futures::Map`
    // directly.
    type Fut = Box<Future<Item = Self::Resp, Error = io::Error>>;

    fn call(&self, req: String) -> Self::Fut {
        self.inner.call(req)
            .map(pipeline::Message::WithoutBody)
            .boxed()
    }
}

/// Serve a service up. Secret sauce here is 'NewService', a helper that must be able to create a
/// new 'Service' for each connection that we receive.
pub fn serve<T>(reactor: ReactorHandle,  addr: SocketAddr, new_service: T) -> io::Result<()>
    where T: NewService<Req = String, Resp = String, Error = io::Error> + Send + 'static {
    try!(server::listen(&reactor, addr, move |stream| {
        // Initialize the pipeline dispatch with the service and the line
        // transport
        let service = LineService { inner: try!(new_service.new_service()) };
        pipeline::Server::new(service, Line::new(stream))
    }));
    Ok(())
}

/// And the client handle.
pub struct Client {
    // The same idea here as `LineService`, except we are mapping it the other
    // direction.
    inner: pipeline::ClientHandle<Line<TcpStream>, Empty<(), io::Error>, io::Error>,
}

impl Service for Client {
    type Req = String;
    type Resp = String;
    type Error = io::Error;
    // Again for simplicity, we are just going to box a future
    type Fut = Box<Future<Item = Self::Resp, Error = io::Error>>;

    fn call(&self, req: String) -> Self::Fut {
        self.inner.call(pipeline::Message::WithoutBody(req))
            .boxed()
    }
}

pub fn connect(reactor: ReactorHandle, addr: &SocketAddr) -> io::Result<Client> {
    let addr = addr.clone();
    let client = pipeline::connect(&reactor, move || {
        let stream = try!(TcpStream::connect(&addr));
        Ok(Line::new(stream))
    });

    Ok(Client { inner: client })
}
<commit_msg>Track Tokio master<commit_after>extern crate tokio;
extern crate futures;

#[macro_use]
extern crate log;

use tokio::{server, Service, NewService};
use tokio::io::{Readiness, Transport};
use tokio::proto::pipeline;
use tokio::reactor::ReactorHandle;
use tokio::tcp::TcpStream;
use tokio::util::future::Empty;
use futures::Future;
use std::{io, mem};
use std::net::SocketAddr;

/// Line transport. This is a pretty bare implementation of a Transport that is chunked into
/// individual lines. The job of a transport is twofold:
///
/// 1) take the bytes that arrive on our 'inner' (e.g. socket) and chunk them down into frames as
///    Transport::In.
/// 2) take the frames as Transport::Out to send out and turn them into bytes. This allows for
///    example for combining multiple frames into one TCP send.
///
/// The Service only deals in The magic here is that 'inner' must implement 'Readiness' - this allows it to play with Tokio's
/// reactor.
pub struct Line<T> {
    inner: T,
    read_buffer: Vec<u8>,
    write_buffer: io::Cursor<Vec<u8>>,
}

impl<T> Line<T>
    where T: io::Read + io::Write + Readiness,
{
    pub fn new(inner: T) -> Line<T> {
        Line {
            inner: inner,
            read_buffer: vec![],
            write_buffer: io::Cursor::new(vec![]),
        }
    }
}

impl<T> Readiness for Line<T>
    where T: Readiness
{
    // Our transport is ready for reading whenever our 'inner'.
    fn is_readable(&self) -> bool {
        self.inner.is_readable()
    }

    // And ready for writing whenever inner is. Below we make sure that we always write everything
    // out to 'inner' whenever it is ready, so our writing buf should always be empty when 'inner'
    // is ready for writing and non-empty if it isn't.
    fn is_writable(&self) -> bool {
        let is_writable = self.write_buffer.position() == self.write_buffer.get_ref().len() as u64;

        if !is_writable {
            assert!(!self.inner.is_writable());
        }

        is_writable
    }
}

/// This defines the chunks written to our transport, i.e. the representation
/// that the `Service` deals with. In our case, the received and sent frames
/// are mostly the same (Strings with io::Error as failures), however they
/// could also be different (for example HttpRequest for In and HttpResponse
/// for Out).
pub type Frame = pipeline::Frame<String, io::Error>;

/// This is a bare-metal implementation of a Transport. We define our frames to be String when
/// reading from the wire, that is 'In' and also String when writing to the wire.
impl<T> Transport for Line<T>
    where T: io::Read + io::Write + Readiness
{
    type In = Frame;
    type Out = Frame;

    /// Read a message from the `Transport`
    fn read(&mut self) -> io::Result<Option<Frame>> {
        loop {
            // First, we check if our read buffer contains a new line - if that is the case, we
            // have one new Frame for the Service to consume. We remove the line from the input
            // buffer and this function will get called by Tokio soon again to see if there are
            // more frames available.
            if let Some(n) = self.read_buffer.iter().position(|b| *b == b'\n') {
                let tail = self.read_buffer.split_off(n+1);
                let mut line = mem::replace(&mut self.read_buffer, tail);

                // Remove the new line
                line.truncate(n);

                return String::from_utf8(line)
                    // For pipelined protocols, the message must be a tuple
                    // of the message payload to be sent to the Service and
                    // Option<Sender<T>> where T is the body chunk type.
                    //
                    // To support streaming bodies, the transport could create
                    // a channel pair, include the receiving end in the message
                    // payload and provide the sending end to the pipeline
                    // protocol dispatcher which will then proxy any body chunk
                    // frame to the Sender.
                    .map(|s| Some(pipeline::Frame::Message(s)))
                    .map_err(|_| io::Error::new(io::ErrorKind::Other, "invalid string"));
            }

            // There was no full line in the input buffer - let's see if anything is on our
            // 'inner'.
            match self.inner.read_to_end(&mut self.read_buffer) {
                Ok(0) => {
                    // The other side hang up - this transport is all done.
                    // TODO(sirver): The use case of this is not entirely clear to me.
                    return Ok(Some(pipeline::Frame::Done));
                },
                Ok(_) => {
                    // Some data was read. The next round in the loop will try to parse it into a
                    // line again.
                }
                Err(e) => {
                    // This would block - i.e. there is no data on the socket. We signal Tokio that
                    // there is right now no full frame available. It will try again the next time
                    // our source signals readiness to read.
                    if e.kind() == io::ErrorKind::WouldBlock {
                        return Ok(None);
                    }

                    // Just a regular error - pass upwards for handling.
                    return Err(e)
                }
            }
        }
    }

    /// Write a message to the `Transport`. This turns the frame we get into a byte string and adds
    /// a newline. It then immediately gets flushed out to 'inner'.
    fn write(&mut self, req: Frame) -> io::Result<Option<()>> {
        match req {
            pipeline::Frame::Message(req) => {
                trace!("writing value; val={:?}", req);
                // Our write buffer can only be non-empty if our 'inner' is not ready for writes.
                // But since we signal to Tokio that our Transport is not ready when 'inner' is not
                // ready it should never try to write to us as long as our write buffer is not
                // empty.
                if self.write_buffer.position() < self.write_buffer.get_ref().len() as u64 {
                    return Err(io::Error::new(io::ErrorKind::Other, "transport has pending writes"));
                }

                let mut bytes = req.into_bytes();
                bytes.push(b'\n');

                self.write_buffer = io::Cursor::new(bytes);
                self.flush()
            }
            _ => unimplemented!(),
        }
    }

    /// Flush pending writes to the socket. This tries to write as much as possible of the data we
    /// have in the write buffer to 'inner'. Since this might block - because inner is not ready,
    /// we have to keep track of what we wrote.
    fn flush(&mut self) -> io::Result<Option<()>> {
        trace!("flushing transport");
        loop {
            // Making the borrow checker happy
            let res = {
                let buf = {
                    let pos = self.write_buffer.position() as usize;
                    let buf = &self.write_buffer.get_ref()[pos..];

                    if buf.is_empty() {
                        trace!("transport flushed");
                        return Ok(Some(()));
                    }

                    trace!("writing; remaining={:?}", buf);

                    buf
                };

                self.inner.write(buf)
            };

            match res {
                Ok(mut n) => {
                    n += self.write_buffer.position() as usize;
                    self.write_buffer.set_position(n as u64)
                }
                Err(e) => {
                    if e.kind() == io::ErrorKind::WouldBlock {
                        trace!("transport flush would block");
                        return Ok(None);
                    }

                    trace!("transport flush error; err={:?}", e);
                    return Err(e)
                }
            }
        }
    }
}

/// The Message type with the `Service`. Since the `Line` protocol does not
/// have any streaming bodies, the body component is hard coded to an empty
/// stream.
pub type Message = pipeline::Message<String, Empty<(), io::Error>>;

/// We want to encapsulate `pipeline::Message`. Since the line protocol does
/// not have any streaming bodies, we can make the service be a request &
/// response of type String. `LineService` takes the service supplied to
/// `serve` and adapts it to work with the `proto::pipeline::Server`
/// requirements.
struct LineService<T> {
    inner: T,
}

impl<T> Service for LineService<T>
    where T: Service<Req = String, Resp = String, Error = io::Error>,
{
    type Req = String;
    type Resp = pipeline::Message<String, Empty<(), io::Error>>;
    type Error = io::Error;

    // To make things easier, we are just going to box the future here, however
    // it is possible to not box the future and refer to `futures::Map`
    // directly.
    type Fut = Box<Future<Item = Self::Resp, Error = io::Error>>;

    fn call(&self, req: String) -> Self::Fut {
        self.inner.call(req)
            .map(pipeline::Message::WithoutBody)
            .boxed()
    }
}

/// Serve a service up. Secret sauce here is 'NewService', a helper that must be able to create a
/// new 'Service' for each connection that we receive.
pub fn serve<T>(reactor: ReactorHandle,  addr: SocketAddr, new_service: T) -> io::Result<()>
    where T: NewService<Req = String, Resp = String, Error = io::Error> + Send + 'static {
    try!(server::listen(&reactor, addr, move |stream| {
        // Initialize the pipeline dispatch with the service and the line
        // transport
        let service = LineService { inner: try!(new_service.new_service()) };
        pipeline::Server::new(service, Line::new(stream))
    }));
    Ok(())
}

/// And the client handle.
pub struct Client {
    // The same idea here as `LineService`, except we are mapping it the other
    // direction.
    inner: pipeline::Client<String, String, Empty<(), io::Error>, io::Error>,
}

impl Service for Client {
    type Req = String;
    type Resp = String;
    type Error = io::Error;
    // Again for simplicity, we are just going to box a future
    type Fut = Box<Future<Item = Self::Resp, Error = io::Error>>;

    fn call(&self, req: String) -> Self::Fut {
        self.inner.call(pipeline::Message::WithoutBody(req))
            .boxed()
    }
}

pub fn connect(reactor: ReactorHandle, addr: &SocketAddr) -> io::Result<Client> {
    let addr = addr.clone();
    let client = pipeline::connect(&reactor, move || {
        let stream = try!(TcpStream::connect(&addr));
        Ok(Line::new(stream))
    });

    Ok(Client { inner: client })
}
<|endoftext|>