<commit_before>#![recursion_limit = "128"]

extern crate proc_macro;
use proc_macro::TokenStream;

extern crate heck;
extern crate syn;

#[macro_use]
extern crate quote;

mod util;
mod tuple;
mod record;
mod map;
mod ex_struct;
mod unit_enum;
mod untagged_enum;

#[proc_macro_derive(NifStruct, attributes(module))]
pub fn nif_struct(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();
    let gen = ex_struct::transcoder_decorator(&ast);
    gen.unwrap().parse().unwrap()
}

#[proc_macro_derive(NifMap)]
pub fn nif_map(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();
    let gen = map::transcoder_decorator(&ast);
    gen.unwrap().parse().unwrap()
}

#[proc_macro_derive(NifTuple)]
pub fn nif_tuple(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();
    let gen = tuple::transcoder_decorator(&ast);
    gen.unwrap().parse().unwrap()
}

#[proc_macro_derive(NifRecord, attributes(tag))]
pub fn nif_record(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();
    let gen = record::transcoder_decorator(&ast);
    gen.unwrap().parse().unwrap()
}

#[proc_macro_derive(NifUnitEnum)]
pub fn nif_unit_enum(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();
    let gen = unit_enum::transcoder_decorator(&ast);
    gen.unwrap().parse().unwrap()
}

#[proc_macro_derive(NifUntaggedEnum)]
pub fn nif_untagged_enum(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();
    let gen = untagged_enum::transcoder_decorator(&ast);
    gen.unwrap().parse().unwrap()
}
<commit_msg>Added documentation on codegen functions. (#155)<commit_after>#![recursion_limit = "128"]

extern crate proc_macro;
use proc_macro::TokenStream;

extern crate heck;
extern crate syn;

#[macro_use]
extern crate quote;

mod util;
mod tuple;
mod record;
mod map;
mod ex_struct;
mod unit_enum;
mod untagged_enum;

/// Implementation of the `NifStruct` macro that lets the user annotate a struct that will
/// be translated directly from an Elixir struct to a Rust struct. For example, the following
/// struct, annotated as such:
///
/// ```text
/// #[derive(Debug, NifStruct)]
/// #[module = "AddStruct"]
/// struct AddStruct {
///    lhs: i32,
///    rhs: i32,
/// }
/// ```
///
/// This would be translated by Rustler into:
///
/// ```text
/// defmodule AddStruct do
///     defstruct lhs: 0, rhs: 0
/// end
/// ```
#[proc_macro_derive(NifStruct, attributes(module))]
pub fn nif_struct(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();
    let gen = ex_struct::transcoder_decorator(&ast);
    gen.unwrap().parse().unwrap()
}

/// Implementation of a macro that lets the user annotate a struct with `NifMap` so that the
/// struct can be encoded or decoded from an Elixir map. For example, the following struct
/// annotated as such:
///
/// ```text
/// #[derive(NifMap)]
/// struct AddMap {
///     lhs: i32,
///     rhs: i32,
/// }
/// ```
///
/// Given the values 33 and 21 for this struct, this would result, when encoded, in an elixir
/// map with two elements like:
///
/// ```text
/// %{lhs: 33, rhs: 21}
/// ```
#[proc_macro_derive(NifMap)]
pub fn nif_map(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();
    let gen = map::transcoder_decorator(&ast);
    gen.unwrap().parse().unwrap()
}

/// Implementation of a macro that lets the user annotate a struct with `NifTuple` so that the
/// struct can be encoded or decoded from an Elixir map. For example, the following struct
/// annotated as such:
///
/// ```text
/// #[derive(NifTuple)]
/// struct AddTuple {
///     lhs: i32,
///     rhs: i32,
/// }
/// ```
///
/// Given the values 33 and 21 for this struct, this would result, when encoded, in an elixir
/// tuple with two elements like:
///
/// ```text
/// {33, 21}
/// ```
///
/// The size of the tuple will depend on the number of elements in the struct.
#[proc_macro_derive(NifTuple)]
pub fn nif_tuple(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();
    let gen = tuple::transcoder_decorator(&ast);
    gen.unwrap().parse().unwrap()
}

/// Implementation of the `NifRecord` macro that lets the user annotate a struct that will
/// be translated directly from an Elixir struct to a Rust struct. For example, the following
/// struct, annotated as such:
///
/// ```text
/// #[derive(Debug, NifRecord)]
/// #[tag = "record"]
/// struct AddRecord {
///    lhs: i32,
///    rhs: i32,
/// }
/// ```
///
/// This would be translated by Rustler into:
///
/// ```text
/// defmodule AddRecord do
///     import Record
///     defrecord :record, [lhs: 1, rhs: 2]
/// end
/// ```
#[proc_macro_derive(NifRecord, attributes(tag))]
pub fn nif_record(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();
    let gen = record::transcoder_decorator(&ast);
    gen.unwrap().parse().unwrap()
}

/// Implementation of the `NifUnitEnum` macro that lets the user annotate an enum with a unit type
/// that will generate elixir atoms when encoded
///
/// ```text
/// #[derive(NifUnitEnum)]
/// enum UnitEnum {
///    FooBar,
///    Baz,
/// }
/// ```
///
/// An example usage in elixir would look like the following.
///
/// ```text
/// test "unit enum transcoder" do
///    assert :foo_bar == RustlerTest.unit_enum_echo(:foo_bar)
///    assert :baz == RustlerTest.unit_enum_echo(:baz)
///    assert :invalid_variant == RustlerTest.unit_enum_echo(:somethingelse)
/// end
/// ```
///
/// Note that the `:invalid_variant` atom is returned if the user tries to encode something
/// that isn't in the Rust enum.
#[proc_macro_derive(NifUnitEnum)]
pub fn nif_unit_enum(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();
    let gen = unit_enum::transcoder_decorator(&ast);
    gen.unwrap().parse().unwrap()
}

/// Implementation of the `NifUntaggedEnum` macro that lets the user annotate an enum that will
/// generate elixir values when decoded. This can be used for rust enums that contain data and
/// will generate a value based on the kind of data encoded. For example from the test code:
///
/// ```text
/// #[derive(NifUntaggedEnum)]
/// enum UntaggedEnum {
///     Foo(u32),
///     Bar(String),
///     Baz(AddStruct),
/// }
///
/// pub fn untagged_enum_echo<'a>(env: Env<'a>, args: &[Term<'a>]) -> NifResult<Term<'a>> {
///     let untagged_enum: UntaggedEnum = args[0].decode()?;
///     Ok(untagged_enum.encode(env))
/// }
/// ```
///
/// This can be used from elixir in the following manner.
///
/// ```text
///   test "untagged enum transcoder" do
///    assert 123 == RustlerTest.untagged_enum_echo(123)
///    assert "Hello" == RustlerTest.untagged_enum_echo("Hello")
///    assert %AddStruct{lhs: 45, rhs: 123} = RustlerTest.untagged_enum_echo(%AddStruct{lhs: 45, rhs: 123})
///    assert :invalid_variant == RustlerTest.untagged_enum_echo([1,2,3,4])
///  end
/// ```
///
/// Note that the type of elixir return is dependent on the data in the enum and the actual enum
/// type is lost in the translation because Elixir has no such concept.
#[proc_macro_derive(NifUntaggedEnum)]
pub fn nif_untagged_enum(input: TokenStream) -> TokenStream {
    let s = input.to_string();
    let ast = syn::parse_macro_input(&s).unwrap();
    let gen = untagged_enum::transcoder_decorator(&ast);
    gen.unwrap().parse().unwrap()
}
<|endoftext|>


<commit_before>extern crate chroniker;

use chroniker::Timer;

//To run this example: cargo run --example getting_started

fn main() {
    //Creates and starts the timer
    let timer = Timer::new();

    //Do some stuff
    chroniker::sleep(250);

    //Print the time it took to run
    println!("Time: {:?}", timer);

    //Do some more operations
    chroniker::sleep(250);

    //Print the results again
    println!("Time: {:?}", timer);

    //Now lets try to reset the results.
    //You can do this by recreating the struct
    //or calling the reset method.
    let mut timer = Timer::new();

    //Do some operations
    chroniker::sleep(250);

    println!("Time: {:?}", timer);

    //Lets reset again
    //Note: Unlike all other functions
    // this requires a mutable timer
    timer.reset();

    //Do some operations
    chroniker::sleep(250);

    println!("Time: {:?}", timer);
}
<commit_msg>Updated Example<commit_after>extern crate chroniker;

use chroniker::Timer;

//To run this example: cargo run --example getting_started

fn main() {
    //Creates and starts the timer
    let timer = Timer::new();

    //Do some stuff
    chroniker::sleep(1100);

    //Print the time it took to run
    println!("Time: {:?}", timer);

    //Do some more operations
    chroniker::sleep(250);

    //Print the results again
    println!("Time: {:?}", timer);

    //Now lets try to reset the results.
    //You can do this by recreating the struct
    //or calling the reset method.
    let mut timer = Timer::new();

    //Do some operations
    chroniker::sleep(250);

    println!("Time: {:?}", timer);

    //Lets reset again
    //Note: Unlike all other functions
    // this requires a mutable timer
    timer.reset();

    //Do some operations
    chroniker::sleep(1750);

    println!("Time: {:?}", timer);
}
<|endoftext|>


<commit_before>use {Error, Parcel, Settings};
use hint;
use std::io::prelude::*;
use std::fmt;

/// A high level abstraction over a lower-level `Parcel`.
///
/// Automatically marshals values to and from the high level
/// and low level types for serialization.
///
/// # Example
///
/// ```
/// #[macro_use] extern crate protocol_derive;
/// extern crate protocol;
///
/// use protocol::Parcel;
///
/// #[derive(Protocol)]
/// pub struct RawPacket {
///     opcode: u8,
///     magic_number: u8,
///     payload: Vec<u8>,
///     version: (u8, u8),
/// }
///
/// #[derive(Debug, Clone)]
/// pub enum Login {
///     Success {
///         message: String,
///     },
///     Failure {
///         code: FailureCode,
///         response: String,
///     },
/// }
///
/// impl protocol::HighLevel for Login {
///     type LowLevel = RawPacket;
///
///     fn into_low_level(self) -> RawPacket {
///         match self {
///             Login::Success { message } => {
///                 RawPacket {
///                     opcode: 0,
///                     magic_number: 0xaa,
///                     payload: message.into_bytes(),
///                     version: (11, 0),
///                 }
///             },
///             Login::Failure { .. } => unimplemented!(),
///         }
///     }
///
///     fn from_low_level(low_level: RawPacket)
///         -> Result<Self, protocol::Error> {
///         match low_level.opcode {
///             0 => Ok(Login::Success { message: String::from_utf8(low_level.payload).unwrap() }),
///             1 => Ok(Login::Failure {
///                 code: FailureCode::MyDogAteMyHomework,
///                 response: String::from_utf8(low_level.payload[1..].to_owned()).unwrap() }),
///             _ => unreachable!(),
///         }
///     }
/// }
///
/// #[derive(Debug, Clone)]
/// pub enum FailureCode {
///     MyDogAteMyHomework,
/// }
///
/// let high_level = Login::Success { message: "Hi!".to_owned() };
/// assert_eq!(11, high_level.raw_bytes(&protocol::Settings::default()).unwrap().len());
/// ```
pub trait HighLevel : Clone + fmt::Debug {
    /// The lower-level representation of this type.
    type LowLevel: Parcel;

    /// Converts this high level type into its lower-level representation.
    fn into_low_level(self) -> Self::LowLevel;

    /// Creates a high-level abstraction over a lower-level value.
    fn from_low_level(value: Self::LowLevel) -> Result<Self, Error>;
}

impl<H> Parcel for H
    where H: HighLevel {
    const TYPE_NAME: &'static str = "HighLevel";

    fn read_field(read: &mut Read,
                  settings: &Settings,
                  hints: &mut hint::Hints) -> Result<Self, Error> {
        let low_level = H::LowLevel::read_field(read, settings, hints)?;
        H::from_low_level(low_level)
    }

    fn write_field(&self,
                   write: &mut Write,
                   settings: &Settings,
                   hints: &mut hint::Hints) -> Result<(), Error> {
        let low_level = self.clone().into_low_level();
        low_level.write_field(write, settings, hints)
    }
}

<commit_msg>Allow HighLevel::from_low_level to read extra data<commit_after>use {Error, Parcel, Settings};
use hint;
use std::io::prelude::*;
use std::fmt;

/// A high level abstraction over a lower-level `Parcel`.
///
/// Automatically marshals values to and from the high level
/// and low level types for serialization.
///
/// # Example
///
/// ```
/// #[macro_use] extern crate protocol_derive;
/// extern crate protocol;
///
/// use protocol::Parcel;
///
/// #[derive(Protocol)]
/// pub struct RawPacket {
///     opcode: u8,
///     magic_number: u8,
///     payload: Vec<u8>,
///     version: (u8, u8),
/// }
///
/// #[derive(Debug, Clone)]
/// pub enum Login {
///     Success {
///         message: String,
///     },
///     Failure {
///         code: FailureCode,
///         response: String,
///     },
/// }
///
/// impl protocol::HighLevel for Login {
///     type LowLevel = RawPacket;
///
///     fn into_low_level(self) -> RawPacket {
///         match self {
///             Login::Success { message } => {
///                 RawPacket {
///                     opcode: 0,
///                     magic_number: 0xaa,
///                     payload: message.into_bytes(),
///                     version: (11, 0),
///                 }
///             },
///             Login::Failure { .. } => unimplemented!(),
///         }
///     }
///
///     fn from_low_level(low_level: RawPacket, _: &mut std::io::Read)
///         -> Result<Self, protocol::Error> {
///         match low_level.opcode {
///             0 => Ok(Login::Success { message: String::from_utf8(low_level.payload).unwrap() }),
///             1 => Ok(Login::Failure {
///                 code: FailureCode::MyDogAteMyHomework,
///                 response: String::from_utf8(low_level.payload[1..].to_owned()).unwrap() }),
///             _ => unreachable!(),
///         }
///     }
/// }
///
/// #[derive(Debug, Clone)]
/// pub enum FailureCode {
///     MyDogAteMyHomework,
/// }
///
/// let high_level = Login::Success { message: "Hi!".to_owned() };
/// assert_eq!(11, high_level.raw_bytes(&protocol::Settings::default()).unwrap().len());
/// ```
pub trait HighLevel : Clone + fmt::Debug {
    /// The lower-level representation of this type.
    type LowLevel: Parcel;

    /// Converts this high level type into its lower-level representation.
    fn into_low_level(self) -> Self::LowLevel;

    /// Creates a high-level abstraction over a lower-level value.
    ///
    /// The method has access to the reader post-parsing of the low level type.
    /// It is not necessary to use this if not needed.
    fn from_low_level(value: Self::LowLevel,
                      subsequent_reader: &mut Read) -> Result<Self, Error>;
}

impl<H> Parcel for H
    where H: HighLevel {
    const TYPE_NAME: &'static str = "HighLevel";

    fn read_field(read: &mut Read,
                  settings: &Settings,
                  hints: &mut hint::Hints) -> Result<Self, Error> {
        let low_level = H::LowLevel::read_field(read, settings, hints)?;
        H::from_low_level(low_level, read)
    }

    fn write_field(&self,
                   write: &mut Write,
                   settings: &Settings,
                   hints: &mut hint::Hints) -> Result<(), Error> {
        let low_level = self.clone().into_low_level();
        low_level.write_field(write, settings, hints)
    }
}

<|endoftext|>


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

use codec::{
    eyre::{bail, eyre, Result},
    stencila_schema::{
        Article, CreativeWorkAuthors, CreativeWorkPublisher, CreativeWorkTitle, CreativeWorkTypes,
        Date, Node, Organization, Periodical, Person, PublicationIssue,
        PublicationIssueIssueNumber, PublicationVolume, PublicationVolumeVolumeNumber,
        ThingIdentifiers,
    },
    utils::vec_string,
    Codec, CodecTrait, DecodeOptions,
};

/// A codec for Citation Style Language (CSL) JSON
///
/// This uses `serde_json` to parse the JSON into a hash map and then extracts
/// various properties from it to populate an instance of one of the `CreativeWork` types,
/// for example, an `Article`, `Book` or `Dataset`.
///
/// The `citeproc-io` crate, which is a part of https://github.com/zotero/citeproc-rs, could be
/// used for parsing CSL-JSON:
///
///    let reference: citeproc_io::Reference = serde_json::from_str(str)?;
///
/// but it was found to be quite strict (e.g did not handle `"type": "journal-article"`)
/// and the parsed `Reference` still needed to be translated to a Stencila node.
pub struct CslCodec {}

impl CodecTrait for CslCodec {
    fn spec() -> Codec {
        Codec {
            formats: vec_string!["csl", "csl-json"],
            root_types: vec_string!["Article"],
            ..Default::default()
        }
    }

    fn from_str(str: &str, _options: Option<DecodeOptions>) -> Result<Node> {
        let data: HashMap<String, serde_json::Value> = serde_json::from_str(str)?;

        let mut article = Article::default();

        if let Some(title) = data.get("title") {
            article.title = Some(Box::new(CreativeWorkTitle::String(decode_string(title)?)));
        }

        if let Some(date) = data.get("published") {
            article.date_published = Some(decode_date(date).map(Box::new)?);
        }
        if let Some(date) = data.get("submitted") {
            article.date_received = Some(decode_date(date).map(Box::new)?);
        }

        if let Some(authors) = data.get("author") {
            let authors = if let Some(authors) = authors.as_array() {
                authors
            } else {
                bail!("Expected `authors` to be an array")
            };
            let authors = authors
                .iter()
                .map(|author| {
                    let person = decode_person(author).unwrap();
                    CreativeWorkAuthors::Person(person)
                })
                .collect();
            article.authors = Some(authors);
        }

        let is_part_of = data
            .get("container-title")
            .and_then(|title| decode_string(title).ok())
            .map(|name| {
                Box::new(CreativeWorkTypes::Periodical(Periodical {
                    name: Some(Box::new(name)),
                    ..Default::default()
                }))
            });

        let is_part_of = if let Some(volume_number) = data.get("volume").and_then(|num| {
            num.as_str()
                .map(|num| PublicationVolumeVolumeNumber::String(num.to_string()))
                .or_else(|| num.as_i64().map(PublicationVolumeVolumeNumber::Integer))
        }) {
            Some(Box::new(CreativeWorkTypes::PublicationVolume(
                PublicationVolume {
                    is_part_of,
                    volume_number: Some(Box::new(volume_number)),
                    ..Default::default()
                },
            )))
        } else {
            is_part_of
        };

        let is_part_of = if let Some(issue_number) = data.get("volume").and_then(|num| {
            num.as_str()
                .map(|num| PublicationIssueIssueNumber::String(num.to_string()))
                .or_else(|| num.as_i64().map(PublicationIssueIssueNumber::Integer))
        }) {
            Some(Box::new(CreativeWorkTypes::PublicationIssue(
                PublicationIssue {
                    is_part_of,
                    issue_number: Some(Box::new(issue_number)),
                    ..Default::default()
                },
            )))
        } else {
            is_part_of
        };

        article.is_part_of = is_part_of;

        if let Some(publisher) = data.get("publisher") {
            let name = decode_string(publisher)?;
            article.publisher = Some(Box::new(CreativeWorkPublisher::Organization(
                Organization {
                    name: Some(Box::new(name)),
                    ..Default::default()
                },
            )));
        }

        Ok(Node::Article(article))
    }
}

/// Decode a `string` variable
fn decode_string(string: &serde_json::Value) -> Result<String> {
    string
        .as_str()
        .map(|str| str.to_string())
        .ok_or_else(|| eyre!("Expected a string value"))
}

/// Decode a `name-variable` into a `Person`
///
/// See https://github.com/citation-style-language/schema/blob/506040022f6c37846343edd36658b23e85b5b8ff/schemas/input/csl-data.json#L463
fn decode_person(data: &serde_json::Value) -> Result<Person> {
    let given_names = data
        .get("given")
        .and_then(|name| name.as_str())
        .map(|name| {
            name.split(' ')
                .map(|name| name.to_string())
                .collect::<Vec<String>>()
        });
    let family_names = data
        .get("family")
        .and_then(|name| name.as_str())
        .map(|name| {
            name.split(' ')
                .map(|name| name.to_string())
                .collect::<Vec<String>>()
        });
    let identifiers = data
        .get("ORCID")
        .or_else(|| data.get("orcid"))
        .and_then(|orcid| orcid.as_str())
        .map(|orcid| vec![ThingIdentifiers::String(orcid.to_string())]);

    Ok(Person {
        given_names,
        family_names,
        identifiers,
        ..Default::default()
    })
}

/// Decode a `date-variable` into a `Date`
///
/// See https://github.com/citation-style-language/schema/blob/506040022f6c37846343edd36658b23e85b5b8ff/schemas/input/csl-data.json#L499
fn decode_date(data: &serde_json::Value) -> Result<Date> {
    let value = if let Some(raw) = data.get("raw") {
        raw.as_str()
            .ok_or_else(|| eyre!("Expected `raw` to be a string"))?
            .to_string()
    } else if let Some(literal) = data.get("literal") {
        literal
            .as_str()
            .ok_or_else(|| eyre!("Expected `literal` to be a string"))?
            .to_string()
    } else if let Some(parts) = data.get("date-parts") {
        let parts = parts
            .as_array()
            .ok_or_else(|| eyre!("Expected `parts` to be an array"))?;
        let parts = parts
            .first()
            .and_then(|item| item.as_array())
            .ok_or_else(|| eyre!("Expected `parts` to have at least one item that is an array"))?;
        let mut date = parts
            .first()
            .and_then(|year| {
                year.as_str()
                    .map(|year| year.to_string())
                    .or_else(|| year.as_u64().map(|year| year.to_string()))
            })
            .ok_or_else(|| eyre!("Expected `year` to be a number"))?;
        if let Some(month) = parts.get(1).and_then(|month| {
            month
                .as_str()
                .map(|month| month.to_string())
                .or_else(|| month.as_u64().map(|month| month.to_string()))
        }) {
            date.push('-');
            date.push_str(&month);
        }
        if let Some(day) = parts.get(2).and_then(|day| {
            day.as_str()
                .map(|day| day.to_string())
                .or_else(|| day.as_u64().map(|day| day.to_string()))
        }) {
            date.push('-');
            date.push_str(&day);
        }
        date
    } else {
        bail!("Unable to parse `Date` from `{:?}`", data)
    };

    Ok(Date {
        value,
        ..Default::default()
    })
}

#[cfg(test)]
mod tests {
    use super::*;
    use test_snaps::{insta::assert_json_snapshot, snapshot_fixtures_content};

    #[test]
    fn fragments() {
        snapshot_fixtures_content("fragments/csl/*.json", |content| {
            let node = CslCodec::from_str(content, None).unwrap();
            assert_json_snapshot!(node);
        });
    }
}
<commit_msg>refactor(CSL codec): Add `from_json` method<commit_after>pub use codec::CodecTrait;
use codec::{
    eyre::{bail, eyre, Result},
    stencila_schema::{
        Article, CreativeWorkAuthors, CreativeWorkPublisher, CreativeWorkTitle, CreativeWorkTypes,
        Date, Node, Organization, Periodical, Person, PublicationIssue,
        PublicationIssueIssueNumber, PublicationVolume, PublicationVolumeVolumeNumber,
        ThingIdentifiers,
    },
    utils::vec_string,
    Codec, DecodeOptions,
};

/// A codec for Citation Style Language (CSL) JSON
///
/// This uses `serde_json` to parse the JSON into a hash map and then extracts
/// various properties from it to populate an instance of one of the `CreativeWork` types,
/// for example, an `Article`, `Book` or `Dataset`.
///
/// The `citeproc-io` crate, which is a part of https://github.com/zotero/citeproc-rs, could be
/// used for parsing CSL-JSON:
///
///    let reference: citeproc_io::Reference = serde_json::from_str(str)?;
///
/// but it was found to be quite strict (e.g did not handle `"type": "journal-article"`)
/// and the parsed `Reference` still needed to be translated to a Stencila node.
pub struct CslCodec;

impl CslCodec {
    pub fn from_json(data: serde_json::Value) -> Result<Node> {
        let mut article = Article::default();

        if let Some(title) = data.get("title") {
            article.title = Some(Box::new(CreativeWorkTitle::String(decode_string(title)?)));
        }

        if let Some(date) = data.get("published") {
            article.date_published = Some(decode_date(date).map(Box::new)?);
        }
        if let Some(date) = data.get("submitted") {
            article.date_received = Some(decode_date(date).map(Box::new)?);
        }

        if let Some(authors) = data.get("author") {
            let authors = if let Some(authors) = authors.as_array() {
                authors
            } else {
                bail!("Expected `authors` to be an array")
            };
            let authors = authors
                .iter()
                .map(|author| {
                    let person = decode_person(author).unwrap();
                    CreativeWorkAuthors::Person(person)
                })
                .collect();
            article.authors = Some(authors);
        }

        let is_part_of = data
            .get("container-title")
            .and_then(|title| decode_string(title).ok())
            .map(|name| {
                Box::new(CreativeWorkTypes::Periodical(Periodical {
                    name: Some(Box::new(name)),
                    ..Default::default()
                }))
            });

        let is_part_of = if let Some(volume_number) = data.get("volume").and_then(|num| {
            num.as_str()
                .map(|num| PublicationVolumeVolumeNumber::String(num.to_string()))
                .or_else(|| num.as_i64().map(PublicationVolumeVolumeNumber::Integer))
        }) {
            Some(Box::new(CreativeWorkTypes::PublicationVolume(
                PublicationVolume {
                    is_part_of,
                    volume_number: Some(Box::new(volume_number)),
                    ..Default::default()
                },
            )))
        } else {
            is_part_of
        };

        let is_part_of = if let Some(issue_number) = data.get("volume").and_then(|num| {
            num.as_str()
                .map(|num| PublicationIssueIssueNumber::String(num.to_string()))
                .or_else(|| num.as_i64().map(PublicationIssueIssueNumber::Integer))
        }) {
            Some(Box::new(CreativeWorkTypes::PublicationIssue(
                PublicationIssue {
                    is_part_of,
                    issue_number: Some(Box::new(issue_number)),
                    ..Default::default()
                },
            )))
        } else {
            is_part_of
        };

        article.is_part_of = is_part_of;

        if let Some(publisher) = data.get("publisher") {
            let name = decode_string(publisher)?;
            article.publisher = Some(Box::new(CreativeWorkPublisher::Organization(
                Organization {
                    name: Some(Box::new(name)),
                    ..Default::default()
                },
            )));
        }

        Ok(Node::Article(article))
    }
}

impl CodecTrait for CslCodec {
    fn spec() -> Codec {
        Codec {
            formats: vec_string!["csl", "csl-json"],
            root_types: vec_string!["Article"],
            ..Default::default()
        }
    }

    fn from_str(str: &str, _options: Option<DecodeOptions>) -> Result<Node> {
        let data = serde_json::from_str(str)?;
        Self::from_json(data)
    }
}

/// Decode a `string` variable
fn decode_string(string: &serde_json::Value) -> Result<String> {
    string
        .as_str()
        .map(|str| str.to_string())
        .ok_or_else(|| eyre!("Expected a string value"))
}

/// Decode a `name-variable` into a `Person`
///
/// See https://github.com/citation-style-language/schema/blob/506040022f6c37846343edd36658b23e85b5b8ff/schemas/input/csl-data.json#L463
fn decode_person(data: &serde_json::Value) -> Result<Person> {
    let given_names = data
        .get("given")
        .and_then(|name| name.as_str())
        .map(|name| {
            name.split(' ')
                .map(|name| name.to_string())
                .collect::<Vec<String>>()
        });
    let family_names = data
        .get("family")
        .and_then(|name| name.as_str())
        .map(|name| {
            name.split(' ')
                .map(|name| name.to_string())
                .collect::<Vec<String>>()
        });
    let identifiers = data
        .get("ORCID")
        .or_else(|| data.get("orcid"))
        .and_then(|orcid| orcid.as_str())
        .map(|orcid| vec![ThingIdentifiers::String(orcid.to_string())]);

    Ok(Person {
        given_names,
        family_names,
        identifiers,
        ..Default::default()
    })
}

/// Decode a `date-variable` into a `Date`
///
/// See https://github.com/citation-style-language/schema/blob/506040022f6c37846343edd36658b23e85b5b8ff/schemas/input/csl-data.json#L499
fn decode_date(data: &serde_json::Value) -> Result<Date> {
    let value = if let Some(raw) = data.get("raw") {
        raw.as_str()
            .ok_or_else(|| eyre!("Expected `raw` to be a string"))?
            .to_string()
    } else if let Some(literal) = data.get("literal") {
        literal
            .as_str()
            .ok_or_else(|| eyre!("Expected `literal` to be a string"))?
            .to_string()
    } else if let Some(parts) = data.get("date-parts") {
        let parts = parts
            .as_array()
            .ok_or_else(|| eyre!("Expected `parts` to be an array"))?;
        let parts = parts
            .first()
            .and_then(|item| item.as_array())
            .ok_or_else(|| eyre!("Expected `parts` to have at least one item that is an array"))?;
        let mut date = parts
            .first()
            .and_then(|year| {
                year.as_str()
                    .map(|year| year.to_string())
                    .or_else(|| year.as_u64().map(|year| year.to_string()))
            })
            .ok_or_else(|| eyre!("Expected `year` to be a number"))?;
        if let Some(month) = parts.get(1).and_then(|month| {
            month
                .as_str()
                .map(|month| month.to_string())
                .or_else(|| month.as_u64().map(|month| month.to_string()))
        }) {
            date.push('-');
            date.push_str(&month);
        }
        if let Some(day) = parts.get(2).and_then(|day| {
            day.as_str()
                .map(|day| day.to_string())
                .or_else(|| day.as_u64().map(|day| day.to_string()))
        }) {
            date.push('-');
            date.push_str(&day);
        }
        date
    } else {
        bail!("Unable to parse `Date` from `{:?}`", data)
    };

    Ok(Date {
        value,
        ..Default::default()
    })
}

#[cfg(test)]
mod tests {
    use super::*;
    use test_snaps::{insta::assert_json_snapshot, snapshot_fixtures_content};

    #[test]
    fn fragments() {
        snapshot_fixtures_content("fragments/csl/*.json", |content| {
            let node = CslCodec::from_str(content, None).unwrap();
            assert_json_snapshot!(node);
        });
    }
}
<|endoftext|>


<commit_before><commit_msg>Do not show the lens with type hints<commit_after><|endoftext|>


<commit_before>use std::cell::{Ref, RefCell};
use std::cmp;
use std::io;
use std::net::{Ipv4Addr, SocketAddr};
use std::rc::{Rc, Weak};
use log::LogLevel;
use mio::{Event, PollOpt, Ready, Token};
use mio::net::TcpStream;

use super::binary;
use super::client::Client;
use super::connection::{self, Connection, ConnectionId};
use super::ipv4_header::IPv4Header;
use super::ipv4_packet::{IPv4Packet, MAX_PACKET_LENGTH};
use super::packet_source::PacketSource;
use super::packetizer::Packetizer;
use super::selector::{EventHandler, Selector};
use super::stream_buffer::StreamBuffer;
use super::tcp_header::{self, TCPHeader};
use super::transport_header::{TransportHeader, TransportHeaderMut};

const TAG: &'static str = "TCPConnection";

const MAX_PAYLOAD_LENGTH: u16 = 1400;

pub struct TCPConnection {
    self_weak: Weak<RefCell<TCPConnection>>,
    id: ConnectionId,
    client: Weak<RefCell<Client>>,
    stream: TcpStream,
    token: Token,
    client_to_network: StreamBuffer,
    network_to_client: Packetizer,
    packet_for_client_length: Option<u16>,
    closed: bool,
    tcb: TCB,
}

struct TCB {
    state: TCPState,
    syn_sequence_number: u32,
    sequence_number: u32,
    acknowledgement_number: u32,
    their_acknowledgement_number: u32,
    client_window: u16,
    remote_closed: bool,
}

#[derive(PartialEq, Eq)]
enum TCPState {
    Init,
    SynSent,
//    SynReceived,
    Established,
    CloseWait,
    LastAck,
}

impl TCB {
    fn new() -> Self {
        Self {
            state: TCPState::Init,
            syn_sequence_number: 0,
            sequence_number: 0,
            acknowledgement_number: 0,
            their_acknowledgement_number: 0,
            client_window: 0,
            remote_closed: false,
        }
    }

    fn numbers(&self) -> String {
        format!("(seq={}, ack={})", self.sequence_number, self.acknowledgement_number)
    }
}

impl TCPConnection {
    pub fn new(selector: &mut Selector, id: ConnectionId, client: Weak<RefCell<Client>>, ipv4_header: &IPv4Header, transport_header: &TransportHeader) -> io::Result<Rc<RefCell<Self>>> {
        let stream = Self::create_stream(&id)?;

        if let TransportHeader::TCP(ref tcp_header) = *transport_header {
            // shrink the TCP options to pass a minimal refrence header to the packetizer
            let mut shrinked_tcp_header_raw = [0u8; 20];
            shrinked_tcp_header_raw.copy_from_slice(&tcp_header.raw()[..20]);
            let mut shrinked_tcp_header_data = tcp_header.data().clone();
            {
                let mut shrinked_tcp_header = shrinked_tcp_header_data.bind_mut(&mut shrinked_tcp_header_raw);
                shrinked_tcp_header.shrink_options();
                assert_eq!(20, shrinked_tcp_header.header_length());
            }

            let shrinked_transport_header = shrinked_tcp_header_data.bind(&shrinked_tcp_header_raw).into();

            let packetizer = Packetizer::new(&ipv4_header, &shrinked_transport_header);

            let rc = Rc::new(RefCell::new(Self {
                self_weak: Weak::new(),
                id: id,
                client: client,
                stream: stream,
                token: Token(0), // default value, will be set afterwards
                client_to_network: StreamBuffer::new(4 * MAX_PACKET_LENGTH),
                network_to_client: packetizer,
                packet_for_client_length: None,
                closed: false,
                tcb: TCB::new(),
            }));

            {
                let mut self_ref = rc.borrow_mut();

                // keep a shared reference to this
                self_ref.self_weak = Rc::downgrade(&rc);

                // rc is an EventHandler, register() expects a Box<EventHandler>
                let handler = Box::new(rc.clone());
                let token = selector.register(&self_ref.stream, handler, Ready::readable(), PollOpt::level())?;
                self_ref.token = token;
            }
            Ok(rc)
        } else {
            panic!("Not a TCP header");
        }
    }

    fn create_stream(id: &ConnectionId) -> io::Result<TcpStream> {
        let rewritten_destination = connection::rewritten_destination(id.destination_ip(), id.destination_port()).into();
        TcpStream::connect(&rewritten_destination)
    }

    fn close(&mut self, selector: &mut Selector) {
        self.closed = true;
        self.disconnect(selector);

        // route is embedded in router which is embedded in client: the client necessarily exists
        let client_rc = self.client.upgrade().expect("expected client not found");
        let mut client = client_rc.borrow_mut();
        client.router().remove(&self.id);
    }

    fn process_send(&mut self, selector: &mut Selector) {
        match self.client_to_network.write_to(&mut self.stream) {
            Ok(w) => if w == 0 {
                self.close(selector);
            },
            Err(err) => {
                error!(target: TAG, "{} Cannot write: {}", self.id, err);
                self.reset_connection(selector);
            },
        }
    }

    fn process_receive(&mut self, selector: &mut Selector) {
        assert!(self.packet_for_client_length.is_none(), "A pending packet was not sent");
        let remaining_client_window = self.get_remaining_client_window();
        assert!(remaining_client_window > 0, "process_received() must not be called when window == 0");
        let max_payload_length = cmp::min(remaining_client_window, MAX_PAYLOAD_LENGTH) as usize;
        Self::update_headers(&mut self.network_to_client, &self.tcb, tcp_header::FLAG_ACK | tcp_header::FLAG_PSH);
        // the packet is bound to the lifetime of self, so we cannot borrow self to call methods
        // defer the other branches in a separate match-block
        let non_lexical_lifetime_workaround = match self.network_to_client.packetize_read(&mut self.stream, Some(max_payload_length)) {
            Ok(Some(ipv4_packet)) => {
                // TODO packet source pull
                Self::send_to_client_ignore(&self.id, &self.client, selector, &ipv4_packet);
                Ok(Some(()))
            },
            Ok(None) => Ok(None),
            Err(err) => Err(err),
        };
        match non_lexical_lifetime_workaround {
            Ok(None) => self.eof(selector),
            Err(err) => {
                error!(target: TAG, "{} Cannot read: {}", self.id, err);
                self.reset_connection(selector);
            },
            Ok(Some(_)) => (), // already handled
        }
    }

    fn send_to_client(client: &Weak<RefCell<Client>>, selector: &mut Selector, ipv4_packet: &IPv4Packet) -> io::Result<()> {
        let client_rc = client.upgrade().expect("expected client not found");
        let mut client = client_rc.borrow_mut();
        client.send_to_client(selector, &ipv4_packet)
    }

    fn send_to_client_ignore(id: &ConnectionId, client: &Weak<RefCell<Client>>, selector: &mut Selector, ipv4_packet: &IPv4Packet) {
        if let Err(err) = Self::send_to_client(client, selector, ipv4_packet) {
            warn!(target: TAG, "{} Cannot send packet to client: {}", id, err);
        }
    }

    fn eof(&mut self, selector: &mut Selector) {
        self.tcb.remote_closed = true;
        if self.tcb.state == TCPState::CloseWait {
            let ipv4_packet = Self::create_empty_response_packet(&self.id, &mut self.network_to_client, &self.tcb, tcp_header::FLAG_FIN);
            self.tcb.sequence_number += 1; // FIN counts for 1 byte
            Self::send_to_client_ignore(&self. id, &self.client, selector, &ipv4_packet);
        }
    }

    fn update_headers(packetizer: &mut Packetizer, tcb: &TCB, flags: u16) {
        if let TransportHeaderMut::TCP(ref mut tcp_header) = packetizer.transport_header_mut() {
            tcp_header.set_sequence_number(tcb.sequence_number);
            tcp_header.set_acknowledgement_number(tcb.acknowledgement_number);
            tcp_header.set_flags(flags);
        } else {
            panic!("Not a TCP header");
        }
    }

    fn create_empty_response_packet<'a>(id: &ConnectionId, packetizer: &'a mut Packetizer, tcb: &TCB, flags: u16) -> IPv4Packet<'a> {
        Self::update_headers(packetizer, tcb, flags);
        debug!(target: TAG, "{} Forging empty response (flags={}) {}", id, flags, tcb.numbers());
        if (flags & tcp_header::FLAG_ACK) != 0 {
            debug!(target: TAG, "{} Acking {}", id, tcb.numbers());
        }
        let ipv4_packet = packetizer.packetize_empty_payload();
        if log_enabled!(target: TAG, LogLevel::Trace) {
            binary::to_string(ipv4_packet.raw());
        }
        ipv4_packet
    }

    fn reset_connection(&mut self, selector: &mut Selector) {
        {
            let ipv4_packet = Self::create_empty_response_packet(&self.id, &mut self.network_to_client, &self.tcb, tcp_header::FLAG_RST);
            Self::send_to_client_ignore(&self.id, &self.client, selector, &ipv4_packet);
        }
        self.close(selector);
    }

    fn update_interests(&mut self, selector: &mut Selector) {
        if !self.closed {
            let mut ready = Ready::empty();
            if self.may_read() {
                ready = ready | Ready::readable()
            }
            if self.may_write() {
                ready = ready | Ready::writable()
            }
            selector.reregister(&self.stream, self.token, ready, PollOpt::level()).expect("Cannot register on poll");
        }
    }

    fn may_read(&self) -> bool {
        !self.tcb.remote_closed &&
                self.packet_for_client_length.is_some() &&
                self.get_remaining_client_window() > 0
    }

    fn may_write(&self) -> bool {
        !self.client_to_network.is_empty()
    }

    fn get_remaining_client_window(&self) -> u16 {
        // TODO
        42
    }
}

impl Connection for TCPConnection {
    fn id(&self) -> &ConnectionId {
        &self.id
    }

    fn send_to_network(&mut self, selector: &mut Selector, ipv4_packet: &IPv4Packet) {
        // TODO
    }

    fn disconnect(&mut self, selector: &mut Selector) {
        info!(target: TAG, "{} Close", self.id);
        selector.deregister(&self.stream, self.token).unwrap();
        // socket will be closed by RAII
    }

    fn is_expired(&self) -> bool {
        // no external timeout expiration
        false
    }
}

impl EventHandler for TCPConnection {
    fn on_ready(&mut self, selector: &mut Selector, event: Event) {
        assert!(!self.closed);
        let ready = event.readiness();
        if ready.is_writable() {
            self.process_send(selector);
        }
        if !self.closed && ready.is_readable() {
            self.process_receive(selector);
        }
        if !self.closed {
            self.update_interests(selector);
        }
    }
}

impl PacketSource for TCPConnection {
    fn get(&mut self) -> Option<IPv4Packet> {
        if let Some(len) = self.packet_for_client_length {
            Some(self.network_to_client.inflate(len))
        } else {
            None
        }
    }

    fn next(&mut self, selector: &mut Selector) {
        let len = self.packet_for_client_length.expect("next() called on empty packet source");
        self.tcb.sequence_number += len as u32;
        self.packet_for_client_length = None;
        self.update_interests(selector);
    }
}
<commit_msg>Wrap seq/ack numbers to accept overflow<commit_after>use std::cell::{Ref, RefCell};
use std::cmp;
use std::io;
use std::net::{Ipv4Addr, SocketAddr};
use std::num::Wrapping;
use std::rc::{Rc, Weak};
use log::LogLevel;
use mio::{Event, PollOpt, Ready, Token};
use mio::net::TcpStream;

use super::binary;
use super::client::Client;
use super::connection::{self, Connection, ConnectionId};
use super::ipv4_header::IPv4Header;
use super::ipv4_packet::{IPv4Packet, MAX_PACKET_LENGTH};
use super::packet_source::PacketSource;
use super::packetizer::Packetizer;
use super::selector::{EventHandler, Selector};
use super::stream_buffer::StreamBuffer;
use super::tcp_header::{self, TCPHeader};
use super::transport_header::{TransportHeader, TransportHeaderMut};

const TAG: &'static str = "TCPConnection";

const MAX_PAYLOAD_LENGTH: u16 = 1400;

pub struct TCPConnection {
    self_weak: Weak<RefCell<TCPConnection>>,
    id: ConnectionId,
    client: Weak<RefCell<Client>>,
    stream: TcpStream,
    token: Token,
    client_to_network: StreamBuffer,
    network_to_client: Packetizer,
    packet_for_client_length: Option<u16>,
    closed: bool,
    tcb: TCB,
}

struct TCB {
    state: TCPState,
    syn_sequence_number: u32,
    sequence_number: Wrapping<u32>,
    acknowledgement_number: Wrapping<u32>,
    their_acknowledgement_number: u32,
    client_window: u16,
    remote_closed: bool,
}

#[derive(PartialEq, Eq)]
enum TCPState {
    Init,
    SynSent,
//    SynReceived,
    Established,
    CloseWait,
    LastAck,
}

impl TCB {
    fn new() -> Self {
        Self {
            state: TCPState::Init,
            syn_sequence_number: 0,
            sequence_number: Wrapping(0),
            acknowledgement_number: Wrapping(0),
            their_acknowledgement_number: 0,
            client_window: 0,
            remote_closed: false,
        }
    }

    fn numbers(&self) -> String {
        format!("(seq={}, ack={})", self.sequence_number, self.acknowledgement_number)
    }
}

impl TCPConnection {
    pub fn new(selector: &mut Selector, id: ConnectionId, client: Weak<RefCell<Client>>, ipv4_header: &IPv4Header, transport_header: &TransportHeader) -> io::Result<Rc<RefCell<Self>>> {
        let stream = Self::create_stream(&id)?;

        if let TransportHeader::TCP(ref tcp_header) = *transport_header {
            // shrink the TCP options to pass a minimal refrence header to the packetizer
            let mut shrinked_tcp_header_raw = [0u8; 20];
            shrinked_tcp_header_raw.copy_from_slice(&tcp_header.raw()[..20]);
            let mut shrinked_tcp_header_data = tcp_header.data().clone();
            {
                let mut shrinked_tcp_header = shrinked_tcp_header_data.bind_mut(&mut shrinked_tcp_header_raw);
                shrinked_tcp_header.shrink_options();
                assert_eq!(20, shrinked_tcp_header.header_length());
            }

            let shrinked_transport_header = shrinked_tcp_header_data.bind(&shrinked_tcp_header_raw).into();

            let packetizer = Packetizer::new(&ipv4_header, &shrinked_transport_header);

            let rc = Rc::new(RefCell::new(Self {
                self_weak: Weak::new(),
                id: id,
                client: client,
                stream: stream,
                token: Token(0), // default value, will be set afterwards
                client_to_network: StreamBuffer::new(4 * MAX_PACKET_LENGTH),
                network_to_client: packetizer,
                packet_for_client_length: None,
                closed: false,
                tcb: TCB::new(),
            }));

            {
                let mut self_ref = rc.borrow_mut();

                // keep a shared reference to this
                self_ref.self_weak = Rc::downgrade(&rc);

                // rc is an EventHandler, register() expects a Box<EventHandler>
                let handler = Box::new(rc.clone());
                let token = selector.register(&self_ref.stream, handler, Ready::readable(), PollOpt::level())?;
                self_ref.token = token;
            }
            Ok(rc)
        } else {
            panic!("Not a TCP header");
        }
    }

    fn create_stream(id: &ConnectionId) -> io::Result<TcpStream> {
        let rewritten_destination = connection::rewritten_destination(id.destination_ip(), id.destination_port()).into();
        TcpStream::connect(&rewritten_destination)
    }

    fn close(&mut self, selector: &mut Selector) {
        self.closed = true;
        self.disconnect(selector);

        // route is embedded in router which is embedded in client: the client necessarily exists
        let client_rc = self.client.upgrade().expect("expected client not found");
        let mut client = client_rc.borrow_mut();
        client.router().remove(&self.id);
    }

    fn process_send(&mut self, selector: &mut Selector) {
        match self.client_to_network.write_to(&mut self.stream) {
            Ok(w) => if w == 0 {
                self.close(selector);
            },
            Err(err) => {
                error!(target: TAG, "{} Cannot write: {}", self.id, err);
                self.reset_connection(selector);
            },
        }
    }

    fn process_receive(&mut self, selector: &mut Selector) {
        assert!(self.packet_for_client_length.is_none(), "A pending packet was not sent");
        let remaining_client_window = self.get_remaining_client_window();
        assert!(remaining_client_window > 0, "process_received() must not be called when window == 0");
        let max_payload_length = cmp::min(remaining_client_window, MAX_PAYLOAD_LENGTH) as usize;
        Self::update_headers(&mut self.network_to_client, &self.tcb, tcp_header::FLAG_ACK | tcp_header::FLAG_PSH);
        // the packet is bound to the lifetime of self, so we cannot borrow self to call methods
        // defer the other branches in a separate match-block
        let non_lexical_lifetime_workaround = match self.network_to_client.packetize_read(&mut self.stream, Some(max_payload_length)) {
            Ok(Some(ipv4_packet)) => {
                // TODO packet source pull
                Self::send_to_client_ignore(&self.id, &self.client, selector, &ipv4_packet);
                Ok(Some(()))
            },
            Ok(None) => Ok(None),
            Err(err) => Err(err),
        };
        match non_lexical_lifetime_workaround {
            Ok(None) => self.eof(selector),
            Err(err) => {
                error!(target: TAG, "{} Cannot read: {}", self.id, err);
                self.reset_connection(selector);
            },
            Ok(Some(_)) => (), // already handled
        }
    }

    fn send_to_client(client: &Weak<RefCell<Client>>, selector: &mut Selector, ipv4_packet: &IPv4Packet) -> io::Result<()> {
        let client_rc = client.upgrade().expect("expected client not found");
        let mut client = client_rc.borrow_mut();
        client.send_to_client(selector, &ipv4_packet)
    }

    fn send_to_client_ignore(id: &ConnectionId, client: &Weak<RefCell<Client>>, selector: &mut Selector, ipv4_packet: &IPv4Packet) {
        if let Err(err) = Self::send_to_client(client, selector, ipv4_packet) {
            warn!(target: TAG, "{} Cannot send packet to client: {}", id, err);
        }
    }

    fn eof(&mut self, selector: &mut Selector) {
        self.tcb.remote_closed = true;
        if self.tcb.state == TCPState::CloseWait {
            let ipv4_packet = Self::create_empty_response_packet(&self.id, &mut self.network_to_client, &self.tcb, tcp_header::FLAG_FIN);
            self.tcb.sequence_number += Wrapping(1); // FIN counts for 1 byte
            Self::send_to_client_ignore(&self. id, &self.client, selector, &ipv4_packet);
        }
    }

    fn update_headers(packetizer: &mut Packetizer, tcb: &TCB, flags: u16) {
        if let TransportHeaderMut::TCP(ref mut tcp_header) = packetizer.transport_header_mut() {
            tcp_header.set_sequence_number(tcb.sequence_number.0);
            tcp_header.set_acknowledgement_number(tcb.acknowledgement_number.0);
            tcp_header.set_flags(flags);
        } else {
            panic!("Not a TCP header");
        }
    }

    fn create_empty_response_packet<'a>(id: &ConnectionId, packetizer: &'a mut Packetizer, tcb: &TCB, flags: u16) -> IPv4Packet<'a> {
        Self::update_headers(packetizer, tcb, flags);
        debug!(target: TAG, "{} Forging empty response (flags={}) {}", id, flags, tcb.numbers());
        if (flags & tcp_header::FLAG_ACK) != 0 {
            debug!(target: TAG, "{} Acking {}", id, tcb.numbers());
        }
        let ipv4_packet = packetizer.packetize_empty_payload();
        if log_enabled!(target: TAG, LogLevel::Trace) {
            binary::to_string(ipv4_packet.raw());
        }
        ipv4_packet
    }

    fn reset_connection(&mut self, selector: &mut Selector) {
        {
            let ipv4_packet = Self::create_empty_response_packet(&self.id, &mut self.network_to_client, &self.tcb, tcp_header::FLAG_RST);
            Self::send_to_client_ignore(&self.id, &self.client, selector, &ipv4_packet);
        }
        self.close(selector);
    }

    fn update_interests(&mut self, selector: &mut Selector) {
        if !self.closed {
            let mut ready = Ready::empty();
            if self.may_read() {
                ready = ready | Ready::readable()
            }
            if self.may_write() {
                ready = ready | Ready::writable()
            }
            selector.reregister(&self.stream, self.token, ready, PollOpt::level()).expect("Cannot register on poll");
        }
    }

    fn may_read(&self) -> bool {
        !self.tcb.remote_closed &&
                self.packet_for_client_length.is_some() &&
                self.get_remaining_client_window() > 0
    }

    fn may_write(&self) -> bool {
        !self.client_to_network.is_empty()
    }

    fn get_remaining_client_window(&self) -> u16 {
        // TODO
        42
    }
}

impl Connection for TCPConnection {
    fn id(&self) -> &ConnectionId {
        &self.id
    }

    fn send_to_network(&mut self, selector: &mut Selector, ipv4_packet: &IPv4Packet) {
        // TODO
    }

    fn disconnect(&mut self, selector: &mut Selector) {
        info!(target: TAG, "{} Close", self.id);
        selector.deregister(&self.stream, self.token).unwrap();
        // socket will be closed by RAII
    }

    fn is_expired(&self) -> bool {
        // no external timeout expiration
        false
    }
}

impl EventHandler for TCPConnection {
    fn on_ready(&mut self, selector: &mut Selector, event: Event) {
        assert!(!self.closed);
        let ready = event.readiness();
        if ready.is_writable() {
            self.process_send(selector);
        }
        if !self.closed && ready.is_readable() {
            self.process_receive(selector);
        }
        if !self.closed {
            self.update_interests(selector);
        }
    }
}

impl PacketSource for TCPConnection {
    fn get(&mut self) -> Option<IPv4Packet> {
        if let Some(len) = self.packet_for_client_length {
            Some(self.network_to_client.inflate(len))
        } else {
            None
        }
    }

    fn next(&mut self, selector: &mut Selector) {
        let len = self.packet_for_client_length.expect("next() called on empty packet source");
        self.tcb.sequence_number += Wrapping(len as u32);
        self.packet_for_client_length = None;
        self.update_interests(selector);
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![feature(unboxed_closures)]

#[plugin]
extern crate glium_macros;

extern crate glutin;
extern crate glium;

use glium::Surface;

mod support;

#[test]
fn clear_color() {
    let display = support::build_display();

    let texture = support::build_renderable_texture(&display);
    texture.as_surface().clear_color(1.0, 0.0, 0.0, 1.0);

    let data: Vec<Vec<(f32, f32, f32)>> = texture.read();

    for row in data.iter() {
        for pixel in row.iter() {
            assert_eq!(pixel, &(1.0, 0.0, 0.0));
        }
    }

    display.assert_no_error();
}

#[test]
fn release_shader_compiler() {
    let display = support::build_display();
    display.release_shader_compiler();
    display.assert_no_error();
}

#[test]
fn viewport_too_large() {
    let display = support::build_display();

    let params = glium::DrawParameters {
        viewport: Some(glium::Rect {
            left: 0,
            bottom: 0,
            width: 4294967295,
            height: 4294967295,
        }),
        .. std::default::Default::default()
    };

    let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display);

    match display.draw().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, &params) {
        Err(glium::DrawError::ViewportTooLarge) => (),
        a => panic!("{:?}", a)
    };

    display.assert_no_error();
}

#[test]
fn timestamp_query() {
    let display = support::build_display();

    let query1 = glium::debug::TimestampQuery::new(&display);
    let query1 = query1.map(|q| q.get());

    let query2 = glium::debug::TimestampQuery::new(&display);
    let query2 = query2.map(|q| q.get());

    match (query1, query2) {
        (Some(q1), Some(q2)) => assert!(q2 >= q1 && q1 != 0),
        _ => ()
    };

    display.assert_no_error();
}

#[test]
fn wrong_depth_range() {
    let display = support::build_display();

    let params = glium::DrawParameters {
        depth_range: (-0.1, 1.0),
        .. std::default::Default::default()
    };

    let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display);

    match display.draw().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, &params) {
        Err(glium::DrawError::InvalidDepthRange) => (),
        a => panic!("{:?}", a)
    };

    display.assert_no_error();
}

#[test]
fn scissor() {
    let display = support::build_display();

    let params = glium::DrawParameters {
        scissor: Some(glium::Rect {
            left: 0,
            bottom: 0,
            width: 1,
            height: 1,
        }),
        .. std::default::Default::default()
    };

    let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display);

    let texture = support::build_renderable_texture(&display);
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, &params).unwrap();

    let data: Vec<Vec<(f32, f32, f32)>> = texture.read();

    assert_eq!(data[0][0], (1.0, 0.0, 0.0));
    assert_eq!(data[1][0], (0.0, 0.0, 0.0));
    assert_eq!(data[0][1], (0.0, 0.0, 0.0));
    assert_eq!(data[1][1], (0.0, 0.0, 0.0));

    for row in data.iter().skip(1) {
        for pixel in row.iter().skip(1) {
            assert_eq!(pixel, &(0.0, 0.0, 0.0));
        }
    }

    display.assert_no_error();
}

#[test]
fn sync() {
    let display = support::build_display();

    let fence = glium::SyncFence::new_if_supported(&display);
    fence.map(|f| f.wait());

    display.assert_no_error();
}

#[test]
fn scissor_followed_by_clear() {
    let display = support::build_display();

    let params = glium::DrawParameters {
        scissor: Some(glium::Rect {
            left: 2,
            bottom: 2,
            width: 2,
            height: 2,
        }),
        .. std::default::Default::default()
    };

    let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display);

    let texture = support::build_renderable_texture(&display);
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms,
                              &params).unwrap();
    texture.as_surface().clear_color(1.0, 0.0, 1.0, 1.0);

    let data: Vec<Vec<(f32, f32, f32, f32)>> = texture.read();
    for row in data.iter() {
        for pixel in row.iter() {
            assert_eq!(pixel, &(1.0, 0.0, 1.0, 1.0));
        }
    }

    display.assert_no_error();
}

#[test]
fn viewport_followed_by_clear() {
    let display = support::build_display();

    let params = glium::DrawParameters {
        viewport: Some(glium::Rect {
            left: 2,
            bottom: 2,
            width: 2,
            height: 2,
        }),
        .. std::default::Default::default()
    };

    let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display);

    let texture = support::build_renderable_texture(&display);
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms,
                              &params).unwrap();
    texture.as_surface().clear_color(1.0, 0.0, 1.0, 1.0);

    let data: Vec<Vec<(f32, f32, f32, f32)>> = texture.read();
    for row in data.iter() {
        for pixel in row.iter() {
            assert_eq!(pixel, &(1.0, 0.0, 1.0, 1.0));
        }
    }

    display.assert_no_error();
}
<commit_msg>Add test for viewport<commit_after>#![feature(plugin)]
#![feature(unboxed_closures)]

#[plugin]
extern crate glium_macros;

extern crate glutin;
extern crate glium;

use glium::Surface;

mod support;

#[test]
fn clear_color() {
    let display = support::build_display();

    let texture = support::build_renderable_texture(&display);
    texture.as_surface().clear_color(1.0, 0.0, 0.0, 1.0);

    let data: Vec<Vec<(f32, f32, f32)>> = texture.read();

    for row in data.iter() {
        for pixel in row.iter() {
            assert_eq!(pixel, &(1.0, 0.0, 0.0));
        }
    }

    display.assert_no_error();
}

#[test]
fn release_shader_compiler() {
    let display = support::build_display();
    display.release_shader_compiler();
    display.assert_no_error();
}

#[test]
fn viewport_too_large() {
    let display = support::build_display();

    let params = glium::DrawParameters {
        viewport: Some(glium::Rect {
            left: 0,
            bottom: 0,
            width: 4294967295,
            height: 4294967295,
        }),
        .. std::default::Default::default()
    };

    let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display);

    match display.draw().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, &params) {
        Err(glium::DrawError::ViewportTooLarge) => (),
        a => panic!("{:?}", a)
    };

    display.assert_no_error();
}

#[test]
fn timestamp_query() {
    let display = support::build_display();

    let query1 = glium::debug::TimestampQuery::new(&display);
    let query1 = query1.map(|q| q.get());

    let query2 = glium::debug::TimestampQuery::new(&display);
    let query2 = query2.map(|q| q.get());

    match (query1, query2) {
        (Some(q1), Some(q2)) => assert!(q2 >= q1 && q1 != 0),
        _ => ()
    };

    display.assert_no_error();
}

#[test]
fn wrong_depth_range() {
    let display = support::build_display();

    let params = glium::DrawParameters {
        depth_range: (-0.1, 1.0),
        .. std::default::Default::default()
    };

    let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display);

    match display.draw().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, &params) {
        Err(glium::DrawError::InvalidDepthRange) => (),
        a => panic!("{:?}", a)
    };

    display.assert_no_error();
}

#[test]
fn scissor() {
    let display = support::build_display();

    let params = glium::DrawParameters {
        scissor: Some(glium::Rect {
            left: 0,
            bottom: 0,
            width: 1,
            height: 1,
        }),
        .. std::default::Default::default()
    };

    let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display);

    let texture = support::build_renderable_texture(&display);
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, &params).unwrap();

    let data: Vec<Vec<(f32, f32, f32)>> = texture.read();

    assert_eq!(data[0][0], (1.0, 0.0, 0.0));
    assert_eq!(data[1][0], (0.0, 0.0, 0.0));
    assert_eq!(data[0][1], (0.0, 0.0, 0.0));
    assert_eq!(data[1][1], (0.0, 0.0, 0.0));

    for row in data.iter().skip(1) {
        for pixel in row.iter().skip(1) {
            assert_eq!(pixel, &(0.0, 0.0, 0.0));
        }
    }

    display.assert_no_error();
}

#[test]
fn sync() {
    let display = support::build_display();

    let fence = glium::SyncFence::new_if_supported(&display);
    fence.map(|f| f.wait());

    display.assert_no_error();
}

#[test]
fn scissor_followed_by_clear() {
    let display = support::build_display();

    let params = glium::DrawParameters {
        scissor: Some(glium::Rect {
            left: 2,
            bottom: 2,
            width: 2,
            height: 2,
        }),
        .. std::default::Default::default()
    };

    let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display);

    let texture = support::build_renderable_texture(&display);
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms,
                              &params).unwrap();
    texture.as_surface().clear_color(1.0, 0.0, 1.0, 1.0);

    let data: Vec<Vec<(f32, f32, f32, f32)>> = texture.read();
    for row in data.iter() {
        for pixel in row.iter() {
            assert_eq!(pixel, &(1.0, 0.0, 1.0, 1.0));
        }
    }

    display.assert_no_error();
}

#[test]
fn viewport_followed_by_clear() {
    let display = support::build_display();

    let params = glium::DrawParameters {
        viewport: Some(glium::Rect {
            left: 2,
            bottom: 2,
            width: 2,
            height: 2,
        }),
        .. std::default::Default::default()
    };

    let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display);

    let texture = support::build_renderable_texture(&display);
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms,
                              &params).unwrap();
    texture.as_surface().clear_color(1.0, 0.0, 1.0, 1.0);

    let data: Vec<Vec<(f32, f32, f32, f32)>> = texture.read();
    for row in data.iter() {
        for pixel in row.iter() {
            assert_eq!(pixel, &(1.0, 0.0, 1.0, 1.0));
        }
    }

    display.assert_no_error();
}

#[test]
fn viewport() {
    let display = support::build_display();

    let params = glium::DrawParameters {
        viewport: Some(glium::Rect {
            left: 0,
            bottom: 0,
            width: 1,
            height: 1,
        }),
        .. std::default::Default::default()
    };

    let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display);

    let texture = support::build_renderable_texture(&display);
    texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, &params).unwrap();

    let data: Vec<Vec<(f32, f32, f32)>> = texture.read();

    assert_eq!(data[0][0], (1.0, 0.0, 0.0));
    assert_eq!(data[1][0], (0.0, 0.0, 0.0));
    assert_eq!(data[0][1], (0.0, 0.0, 0.0));
    assert_eq!(data[1][1], (0.0, 0.0, 0.0));

    for row in data.iter().skip(1) {
        for pixel in row.iter().skip(1) {
            assert_eq!(pixel, &(0.0, 0.0, 0.0));
        }
    }

    display.assert_no_error();
}
<|endoftext|>


<commit_before>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use ty::{self, Lift, TyCtxt, Region};
use rustc_data_structures::transitive_relation::TransitiveRelation;

#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct FreeRegionMap<'tcx> {
    // Stores the relation `a < b`, where `a` and `b` are regions.
    //
    // Invariant: only free regions like `'x` or `'static` are stored
    // in this relation, not scopes.
    relation: TransitiveRelation<Region<'tcx>>
}

impl<'tcx> FreeRegionMap<'tcx> {
    pub fn new() -> Self {
        FreeRegionMap { relation: TransitiveRelation::new() }
    }

    pub fn is_empty(&self) -> bool {
        self.relation.is_empty()
    }

    // Record that `'sup:'sub`. Or, put another way, `'sub <= 'sup`.
    // (with the exception that `'static: 'x` is not notable)
    pub fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) {
        debug!("relate_regions(sub={:?}, sup={:?})", sub, sup);
        if is_free_or_static(sub) && is_free(sup) {
            self.relation.add(sub, sup)
        }
    }

    /// Tests whether `r_a <= sup`. Both must be free regions or
    /// `'static`.
    pub fn sub_free_regions<'a, 'gcx>(&self,
                                      r_a: Region<'tcx>,
                                      r_b: Region<'tcx>)
                                      -> bool {
        assert!(is_free_or_static(r_a) && is_free_or_static(r_b));
        if let ty::ReStatic = r_b {
            true // `'a <= 'static` is just always true, and not stored in the relation explicitly
        } else {
            r_a == r_b || self.relation.contains(&r_a, &r_b)
        }
    }

    /// Compute the least-upper-bound of two free regions. In some
    /// cases, this is more conservative than necessary, in order to
    /// avoid making arbitrary choices. See
    /// `TransitiveRelation::postdom_upper_bound` for more details.
    pub fn lub_free_regions<'a, 'gcx>(&self,
                                      tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                      r_a: Region<'tcx>,
                                      r_b: Region<'tcx>)
                                      -> Region<'tcx> {
        debug!("lub_free_regions(r_a={:?}, r_b={:?})", r_a, r_b);
        assert!(is_free(r_a));
        assert!(is_free(r_b));
        let result = if r_a == r_b { r_a } else {
            match self.relation.postdom_upper_bound(&r_a, &r_b) {
                None => tcx.mk_region(ty::ReStatic),
                Some(r) => *r,
            }
        };
        debug!("lub_free_regions(r_a={:?}, r_b={:?}) = {:?}", r_a, r_b, result);
        result
    }
}

fn is_free(r: Region) -> bool {
    match *r {
        ty::ReEarlyBound(_) | ty::ReFree(_) => true,
        _ => false
    }
}

fn is_free_or_static(r: Region) -> bool {
    match *r {
        ty::ReStatic => true,
        _ => is_free(r),
    }
}

impl_stable_hash_for!(struct FreeRegionMap<'tcx> {
    relation
});

impl<'a, 'tcx> Lift<'tcx> for FreeRegionMap<'a> {
    type Lifted = FreeRegionMap<'tcx>;
    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<FreeRegionMap<'tcx>> {
        self.relation.maybe_map(|&fr| fr.lift_to_tcx(tcx))
                     .map(|relation| FreeRegionMap { relation })
    }
}
<commit_msg>free_region_map: Fix typo in comment: r_a <= r_b<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use ty::{self, Lift, TyCtxt, Region};
use rustc_data_structures::transitive_relation::TransitiveRelation;

#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct FreeRegionMap<'tcx> {
    // Stores the relation `a < b`, where `a` and `b` are regions.
    //
    // Invariant: only free regions like `'x` or `'static` are stored
    // in this relation, not scopes.
    relation: TransitiveRelation<Region<'tcx>>
}

impl<'tcx> FreeRegionMap<'tcx> {
    pub fn new() -> Self {
        FreeRegionMap { relation: TransitiveRelation::new() }
    }

    pub fn is_empty(&self) -> bool {
        self.relation.is_empty()
    }

    // Record that `'sup:'sub`. Or, put another way, `'sub <= 'sup`.
    // (with the exception that `'static: 'x` is not notable)
    pub fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) {
        debug!("relate_regions(sub={:?}, sup={:?})", sub, sup);
        if is_free_or_static(sub) && is_free(sup) {
            self.relation.add(sub, sup)
        }
    }

    /// Tests whether `r_a <= r_b`. Both must be free regions or
    /// `'static`.
    pub fn sub_free_regions<'a, 'gcx>(&self,
                                      r_a: Region<'tcx>,
                                      r_b: Region<'tcx>)
                                      -> bool {
        assert!(is_free_or_static(r_a) && is_free_or_static(r_b));
        if let ty::ReStatic = r_b {
            true // `'a <= 'static` is just always true, and not stored in the relation explicitly
        } else {
            r_a == r_b || self.relation.contains(&r_a, &r_b)
        }
    }

    /// Compute the least-upper-bound of two free regions. In some
    /// cases, this is more conservative than necessary, in order to
    /// avoid making arbitrary choices. See
    /// `TransitiveRelation::postdom_upper_bound` for more details.
    pub fn lub_free_regions<'a, 'gcx>(&self,
                                      tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                      r_a: Region<'tcx>,
                                      r_b: Region<'tcx>)
                                      -> Region<'tcx> {
        debug!("lub_free_regions(r_a={:?}, r_b={:?})", r_a, r_b);
        assert!(is_free(r_a));
        assert!(is_free(r_b));
        let result = if r_a == r_b { r_a } else {
            match self.relation.postdom_upper_bound(&r_a, &r_b) {
                None => tcx.mk_region(ty::ReStatic),
                Some(r) => *r,
            }
        };
        debug!("lub_free_regions(r_a={:?}, r_b={:?}) = {:?}", r_a, r_b, result);
        result
    }
}

fn is_free(r: Region) -> bool {
    match *r {
        ty::ReEarlyBound(_) | ty::ReFree(_) => true,
        _ => false
    }
}

fn is_free_or_static(r: Region) -> bool {
    match *r {
        ty::ReStatic => true,
        _ => is_free(r),
    }
}

impl_stable_hash_for!(struct FreeRegionMap<'tcx> {
    relation
});

impl<'a, 'tcx> Lift<'tcx> for FreeRegionMap<'a> {
    type Lifted = FreeRegionMap<'tcx>;
    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<FreeRegionMap<'tcx>> {
        self.relation.maybe_map(|&fr| fr.lift_to_tcx(tcx))
                     .map(|relation| FreeRegionMap { relation })
    }
}
<|endoftext|>


<commit_before>//
// Sysinfo
//
// Copyright (c) 2018 Guillaume Gomez
//

extern crate sysinfo;

#[test]
fn test_process() {
    #[cfg(not(windows))]
    use sysinfo::ProcessExt;
    use sysinfo::SystemExt;

    let mut s = sysinfo::System::new();
    s.refresh_processes();
    assert!(s.get_process_list().len() != 0);
    #[cfg(not(windows))]
    assert!(s
        .get_process_list()
        .values()
        .any(|p| p.exe().to_str().unwrap_or_else(|| "").len() != 0));
}
<commit_msg>Ensure that System::new doesn't generate Process list<commit_after>//
// Sysinfo
//
// Copyright (c) 2018 Guillaume Gomez
//

extern crate sysinfo;

#[test]
fn test_process() {
    #[cfg(not(windows))]
    use sysinfo::ProcessExt;
    use sysinfo::SystemExt;

    let mut s = sysinfo::System::new();
    assert_eq!(s.get_process_list().len(), 0);
    s.refresh_processes();
    assert!(s.get_process_list().len() != 0);
    #[cfg(not(windows))]
    assert!(s
        .get_process_list()
        .values()
        .any(|p| p.exe().to_str().unwrap_or_else(|| "").len() != 0));
}
<|endoftext|>


<commit_before>//! # Functions and types used by generated protobuf code
//!
//! These are not considered to be public API of rust-protobuf,
//! so they can be changed any time (provided compatibility with
//! previously generated code is preserved).

pub use crate::cached_size::CachedSize;
use crate::coded_input_stream::CodedInputStream;
use crate::coded_output_stream::CodedOutputStream;
use crate::enums::Enum;
use crate::error::Result;
pub use crate::lazy::Lazy;
pub use crate::wire_format::WireType;
use crate::zigzag::*;
use crate::EnumOrUnknown;
use crate::Message;
use crate::MessageField;

pub(crate) mod map;
pub(crate) mod repeated;
pub(crate) mod unsorted;
pub use map::compute_map_size;
pub use map::read_map_into;
pub use map::write_map_with_cached_sizes;
pub use repeated::read_repeated_packed_enum_or_unknown_into;
pub use unsorted::read_unknown_or_skip_group;
pub use unsorted::unknown_fields_size;

use crate::varint::encode::encoded_varint64_len;

/// Given `u64` value compute varint encoded length.
pub fn compute_raw_varint64_size(value: u64) -> u64 {
    encoded_varint64_len(value) as u64
}

/// Given `u32` value compute varint encoded length.
pub fn compute_raw_varint32_size(value: u32) -> u64 {
    compute_raw_varint64_size(value as u64)
}

/// Given `usize` value compute varint encoded length.
pub fn compute_raw_varint_usize_size(value: usize) -> u64 {
    compute_raw_varint64_size(value as u64)
}

/// Fixed size integers.
pub trait ProtobufFixed {
    /// Size of this fixed type in bytes.
    const LEN: u32;
}

/// Helper trait implemented by integer types which could be encoded as varint.
pub trait ProtobufVarint {
    /// Size of self when encoded as varint.
    fn len_varint(&self) -> u64;
}

/// Helper trait implemented by integer types which could be encoded as zigzag varint.
pub trait ProtobufVarintZigzag {
    /// Size of self when encoded as zigzag varint.
    fn len_varint_zigzag(&self) -> u64;
}

impl ProtobufVarint for u64 {
    fn len_varint(&self) -> u64 {
        compute_raw_varint64_size(*self)
    }
}

impl ProtobufVarint for u32 {
    fn len_varint(&self) -> u64 {
        (*self as u64).len_varint()
    }
}

impl ProtobufVarint for i64 {
    fn len_varint(&self) -> u64 {
        // same as length of u64
        (*self as u64).len_varint()
    }
}

impl ProtobufVarintZigzag for i64 {
    fn len_varint_zigzag(&self) -> u64 {
        compute_raw_varint64_size(encode_zig_zag_64(*self))
    }
}

impl ProtobufVarint for i32 {
    fn len_varint(&self) -> u64 {
        // sign-extend and then compute
        (*self as i64).len_varint()
    }
}

impl ProtobufVarintZigzag for i32 {
    fn len_varint_zigzag(&self) -> u64 {
        compute_raw_varint32_size(encode_zig_zag_32(*self))
    }
}

impl ProtobufVarint for bool {
    fn len_varint(&self) -> u64 {
        1
    }
}

impl ProtobufFixed for u32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for i32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for u64 {
    const LEN: u32 = 8;
}

impl ProtobufFixed for i64 {
    const LEN: u32 = 8;
}

impl ProtobufFixed for f32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for f64 {
    const LEN: u32 = 8;
}

/// Technically `bool` is not fixed, but it can be considered as fixed
/// for the purpose of encoding.
impl ProtobufFixed for bool {
    const LEN: u32 = 1;
}

/// Size of serialized repeated packed field, excluding length and tag.
pub fn vec_packed_varint_data_size<T: ProtobufVarint>(vec: &[T]) -> u64 {
    vec.iter()
        .map(|v| v.len_varint() as u64)
        .fold(0, |a, i| a + i)
}

/// Size of serialized repeated packed field, excluding length and tag.
pub fn vec_packed_varint_zigzag_data_size<T: ProtobufVarintZigzag>(vec: &[T]) -> u64 {
    vec.iter()
        .map(|v| v.len_varint_zigzag())
        .fold(0, |a, i| a + i)
}

/// Size of serialized repeated packed enum field, excluding length and tag.
pub fn vec_packed_enum_or_unknown_data_size<E: Enum>(vec: &[EnumOrUnknown<E>]) -> u64 {
    vec.iter()
        .map(|e| compute_raw_varint32_size(e.value() as u32))
        .fold(0, |a, i| a + i)
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_varint_size<T: ProtobufVarint>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_varint_zigzag_size<T: ProtobufVarintZigzag>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_zigzag_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_enum_or_unknown_size<E: Enum>(
    field_number: u32,
    vec: &[EnumOrUnknown<E>],
) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_enum_or_unknown_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute data size of fixed encoding of repeated field data.
pub(crate) fn vec_packed_fixed_data_size<V: ProtobufFixed>(vec: &[V]) -> u64 {
    (vec.len() as u64) * (V::LEN as u64)
}

/// Compute field size (data plus header) of fixed encoding of repeated field.
pub fn vec_packed_fixed_size<V: ProtobufFixed>(field_number: u32, vec: &[V]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_fixed_data_size::<V>(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute tag size. Size of tag does not depend on wire type.
pub fn tag_size(field_number: u32) -> u64 {
    encoded_varint64_len((field_number as u64) << 3) as u64
}

fn value_size_no_tag<T: ProtobufVarint>(value: T, wt: WireType) -> u64 {
    match wt {
        WireType::Fixed64 => 8,
        WireType::Fixed32 => 4,
        WireType::Varint => value.len_varint(),
        _ => panic!(),
    }
}

/// Integer value size when encoded as specified wire type.
pub fn value_size<T: ProtobufVarint>(field_number: u32, value: T, wt: WireType) -> u64 {
    tag_size(field_number) + value_size_no_tag(value, wt)
}

/// Integer value size when encoded as specified wire type.
pub(crate) fn value_varint_zigzag_size_no_tag<T: ProtobufVarintZigzag>(value: T) -> u64 {
    value.len_varint_zigzag()
}

/// Length of value when encoding with zigzag encoding with tag
pub fn value_varint_zigzag_size<T: ProtobufVarintZigzag>(field_number: u32, value: T) -> u64 {
    tag_size(field_number) + value_varint_zigzag_size_no_tag(value)
}

fn enum_or_unknown_size_no_tag<E: Enum>(value: EnumOrUnknown<E>) -> u64 {
    value.value().len_varint() as u64
}

/// Size of encoded enum field value.
pub fn enum_or_unknown_size<E: Enum>(field_number: u32, value: EnumOrUnknown<E>) -> u64 {
    tag_size(field_number) + enum_or_unknown_size_no_tag(value)
}

/// Size of encoded bytes field.
pub(crate) fn bytes_size_no_tag(bytes: &[u8]) -> u64 {
    compute_raw_varint64_size(bytes.len() as u64) + bytes.len() as u64
}

/// Size of encoded bytes field.
pub fn bytes_size(field_number: u32, bytes: &[u8]) -> u64 {
    tag_size(field_number) + bytes_size_no_tag(bytes)
}

/// Size of encoded string field.
pub(crate) fn string_size_no_tag(s: &str) -> u64 {
    bytes_size_no_tag(s.as_bytes())
}

/// Size of encoded string field.
pub fn string_size(field_number: u32, s: &str) -> u64 {
    tag_size(field_number) + string_size_no_tag(s)
}

/// Read singular `message` field.
pub fn read_singular_message_into_field<M>(
    is: &mut CodedInputStream,
    target: &mut MessageField<M>,
) -> Result<()>
where
    M: Message,
{
    let mut m = M::new();
    is.merge_message(&mut m)?;
    *target = MessageField::some(m);
    Ok(())
}

/// Write message with field number and length to the stream.
pub fn write_message_field_with_cached_size<M>(
    field_number: u32,
    message: &M,
    os: &mut CodedOutputStream,
) -> Result<()>
where
    M: Message,
{
    os.write_tag(field_number, WireType::LengthDelimited)?;
    os.write_raw_varint32(message.cached_size())?;
    message.write_to_with_cached_sizes(os)
}
<commit_msg>Dead code<commit_after>//! # Functions and types used by generated protobuf code
//!
//! These are not considered to be public API of rust-protobuf,
//! so they can be changed any time (provided compatibility with
//! previously generated code is preserved).

pub use crate::cached_size::CachedSize;
use crate::coded_input_stream::CodedInputStream;
use crate::coded_output_stream::CodedOutputStream;
use crate::enums::Enum;
use crate::error::Result;
pub use crate::lazy::Lazy;
pub use crate::wire_format::WireType;
use crate::zigzag::*;
use crate::EnumOrUnknown;
use crate::Message;
use crate::MessageField;

pub(crate) mod map;
pub(crate) mod repeated;
pub(crate) mod unsorted;
pub use map::compute_map_size;
pub use map::read_map_into;
pub use map::write_map_with_cached_sizes;
pub use repeated::read_repeated_packed_enum_or_unknown_into;
pub use unsorted::read_unknown_or_skip_group;
pub use unsorted::unknown_fields_size;

use crate::varint::encode::encoded_varint64_len;

/// Given `u64` value compute varint encoded length.
pub fn compute_raw_varint64_size(value: u64) -> u64 {
    encoded_varint64_len(value) as u64
}

/// Given `u32` value compute varint encoded length.
pub fn compute_raw_varint32_size(value: u32) -> u64 {
    compute_raw_varint64_size(value as u64)
}

/// Fixed size integers.
pub trait ProtobufFixed {
    /// Size of this fixed type in bytes.
    const LEN: u32;
}

/// Helper trait implemented by integer types which could be encoded as varint.
pub trait ProtobufVarint {
    /// Size of self when encoded as varint.
    fn len_varint(&self) -> u64;
}

/// Helper trait implemented by integer types which could be encoded as zigzag varint.
pub trait ProtobufVarintZigzag {
    /// Size of self when encoded as zigzag varint.
    fn len_varint_zigzag(&self) -> u64;
}

impl ProtobufVarint for u64 {
    fn len_varint(&self) -> u64 {
        compute_raw_varint64_size(*self)
    }
}

impl ProtobufVarint for u32 {
    fn len_varint(&self) -> u64 {
        (*self as u64).len_varint()
    }
}

impl ProtobufVarint for i64 {
    fn len_varint(&self) -> u64 {
        // same as length of u64
        (*self as u64).len_varint()
    }
}

impl ProtobufVarintZigzag for i64 {
    fn len_varint_zigzag(&self) -> u64 {
        compute_raw_varint64_size(encode_zig_zag_64(*self))
    }
}

impl ProtobufVarint for i32 {
    fn len_varint(&self) -> u64 {
        // sign-extend and then compute
        (*self as i64).len_varint()
    }
}

impl ProtobufVarintZigzag for i32 {
    fn len_varint_zigzag(&self) -> u64 {
        compute_raw_varint32_size(encode_zig_zag_32(*self))
    }
}

impl ProtobufVarint for bool {
    fn len_varint(&self) -> u64 {
        1
    }
}

impl ProtobufFixed for u32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for i32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for u64 {
    const LEN: u32 = 8;
}

impl ProtobufFixed for i64 {
    const LEN: u32 = 8;
}

impl ProtobufFixed for f32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for f64 {
    const LEN: u32 = 8;
}

/// Technically `bool` is not fixed, but it can be considered as fixed
/// for the purpose of encoding.
impl ProtobufFixed for bool {
    const LEN: u32 = 1;
}

/// Size of serialized repeated packed field, excluding length and tag.
pub fn vec_packed_varint_data_size<T: ProtobufVarint>(vec: &[T]) -> u64 {
    vec.iter()
        .map(|v| v.len_varint() as u64)
        .fold(0, |a, i| a + i)
}

/// Size of serialized repeated packed field, excluding length and tag.
pub fn vec_packed_varint_zigzag_data_size<T: ProtobufVarintZigzag>(vec: &[T]) -> u64 {
    vec.iter()
        .map(|v| v.len_varint_zigzag())
        .fold(0, |a, i| a + i)
}

/// Size of serialized repeated packed enum field, excluding length and tag.
pub fn vec_packed_enum_or_unknown_data_size<E: Enum>(vec: &[EnumOrUnknown<E>]) -> u64 {
    vec.iter()
        .map(|e| compute_raw_varint32_size(e.value() as u32))
        .fold(0, |a, i| a + i)
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_varint_size<T: ProtobufVarint>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_varint_zigzag_size<T: ProtobufVarintZigzag>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_zigzag_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_enum_or_unknown_size<E: Enum>(
    field_number: u32,
    vec: &[EnumOrUnknown<E>],
) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_enum_or_unknown_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute data size of fixed encoding of repeated field data.
pub(crate) fn vec_packed_fixed_data_size<V: ProtobufFixed>(vec: &[V]) -> u64 {
    (vec.len() as u64) * (V::LEN as u64)
}

/// Compute field size (data plus header) of fixed encoding of repeated field.
pub fn vec_packed_fixed_size<V: ProtobufFixed>(field_number: u32, vec: &[V]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_fixed_data_size::<V>(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute tag size. Size of tag does not depend on wire type.
pub fn tag_size(field_number: u32) -> u64 {
    encoded_varint64_len((field_number as u64) << 3) as u64
}

fn value_size_no_tag<T: ProtobufVarint>(value: T, wt: WireType) -> u64 {
    match wt {
        WireType::Fixed64 => 8,
        WireType::Fixed32 => 4,
        WireType::Varint => value.len_varint(),
        _ => panic!(),
    }
}

/// Integer value size when encoded as specified wire type.
pub fn value_size<T: ProtobufVarint>(field_number: u32, value: T, wt: WireType) -> u64 {
    tag_size(field_number) + value_size_no_tag(value, wt)
}

/// Integer value size when encoded as specified wire type.
pub(crate) fn value_varint_zigzag_size_no_tag<T: ProtobufVarintZigzag>(value: T) -> u64 {
    value.len_varint_zigzag()
}

/// Length of value when encoding with zigzag encoding with tag
pub fn value_varint_zigzag_size<T: ProtobufVarintZigzag>(field_number: u32, value: T) -> u64 {
    tag_size(field_number) + value_varint_zigzag_size_no_tag(value)
}

fn enum_or_unknown_size_no_tag<E: Enum>(value: EnumOrUnknown<E>) -> u64 {
    value.value().len_varint() as u64
}

/// Size of encoded enum field value.
pub fn enum_or_unknown_size<E: Enum>(field_number: u32, value: EnumOrUnknown<E>) -> u64 {
    tag_size(field_number) + enum_or_unknown_size_no_tag(value)
}

/// Size of encoded bytes field.
pub(crate) fn bytes_size_no_tag(bytes: &[u8]) -> u64 {
    compute_raw_varint64_size(bytes.len() as u64) + bytes.len() as u64
}

/// Size of encoded bytes field.
pub fn bytes_size(field_number: u32, bytes: &[u8]) -> u64 {
    tag_size(field_number) + bytes_size_no_tag(bytes)
}

/// Size of encoded string field.
pub(crate) fn string_size_no_tag(s: &str) -> u64 {
    bytes_size_no_tag(s.as_bytes())
}

/// Size of encoded string field.
pub fn string_size(field_number: u32, s: &str) -> u64 {
    tag_size(field_number) + string_size_no_tag(s)
}

/// Read singular `message` field.
pub fn read_singular_message_into_field<M>(
    is: &mut CodedInputStream,
    target: &mut MessageField<M>,
) -> Result<()>
where
    M: Message,
{
    let mut m = M::new();
    is.merge_message(&mut m)?;
    *target = MessageField::some(m);
    Ok(())
}

/// Write message with field number and length to the stream.
pub fn write_message_field_with_cached_size<M>(
    field_number: u32,
    message: &M,
    os: &mut CodedOutputStream,
) -> Result<()>
where
    M: Message,
{
    os.write_tag(field_number, WireType::LengthDelimited)?;
    os.write_raw_varint32(message.cached_size())?;
    message.write_to_with_cached_sizes(os)
}
<|endoftext|>