<commit_before>#[crate_id = "redis#0.1"];
#[crate_type = "lib"];
#[comment = "Bindings and wrapper functions for redis."];

#[deny(non_camel_case_types)];
#[feature(macro_rules)];
#[feature(globs)];

extern mod extra;

pub use parser::parse_redis_value;
pub use parser::Parser;
pub use enums::*;

pub use client::Client;
pub use script::Script;
pub use connection::Connection;

mod parser;
mod client;
mod script;
mod enums;
mod utils;
mod connection;
mod scan;
<commit_msg>Added license meta information<commit_after>#[crate_id = "redis#0.1"];
#[crate_type = "lib"];
#[license = "BSD"];
#[comment = "Bindings and wrapper functions for redis."];

#[deny(non_camel_case_types)];
#[feature(macro_rules)];
#[feature(globs)];

extern mod extra;

pub use parser::parse_redis_value;
pub use parser::Parser;
pub use enums::*;

pub use client::Client;
pub use script::Script;
pub use connection::Connection;

mod parser;
mod client;
mod script;
mod enums;
mod utils;
mod connection;
mod scan;
<|endoftext|>


<commit_before>// pest. The Elegant Parser
// Copyright (c) 2018 Dragoș Tiselice
//
// 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. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

#[derive(Debug)]
pub struct Stack<T: Clone> {
    ops: Vec<StackOp<T>>,
    cache: Vec<T>
}

impl<T: Clone> Stack<T> {
    pub fn new() -> Self {
        Stack {
            ops: vec![],
            cache: vec![]
        }
    }

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

    pub fn peek(&self) -> Option<&T> {
        self.cache.last()
    }

    pub fn push(&mut self, elem: T) {
        self.ops.push(StackOp::Push(elem.clone()));
        self.cache.push(elem);
    }

    pub fn pop(&mut self) -> Option<T> {
        self.ops.push(StackOp::Pop());
        self.cache.pop()
    }

    pub fn backtrack(&mut self, index: usize) {
        self.ops.truncate(index);
        self.cache();
    }

    fn cache(&mut self) {
        self.cache.clear();
        for op in self.ops.iter() {
            match op {
                &StackOp::Push(ref elem) => {
                    self.cache.push(elem.clone());
                },
                &StackOp::Pop() => {
                    self.cache.pop();
                }
            }
        }
    }
}

#[derive(Debug)]
enum StackOp<T> {
    Push(T),
    Pop()
}

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

    #[test]
    fn stack_ops() {
        let mut stack = Stack::new();

        // []
        assert!(stack.is_empty());
        assert_eq!(stack.peek(), None);
        assert_eq!(stack.pop(), None);

        // [0]
        stack.push(0);
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&0));

        // [0, 1]
        stack.push(1);
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&1));

        // [0]
        assert_eq!(stack.pop(), Some(1));
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&0));

        // [0, 2]
        stack.push(2);
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&2));

        // [0, 2, 3]
        stack.push(3);
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&3));

        // [0, 2]
        assert_eq!(stack.pop(), Some(3));
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&2));

        // [0]
        assert_eq!(stack.pop(), Some(2));
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&0));

        // []
        assert_eq!(stack.pop(), Some(0));
        assert!(stack.is_empty());
        assert_eq!(stack.peek(), None);
        assert_eq!(stack.pop(), None);

        // Test backtracking
        // [0, 2]
        stack.backtrack(5);
        assert_eq!(stack.peek(), Some(&2));
    }
}
<commit_msg>store a vec of snapshots. This will allow us to "rewind" the stack to the state it was when snapshot was last called<commit_after>// pest. The Elegant Parser
// Copyright (c) 2018 Dragoș Tiselice
//
// 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. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

#[derive(Debug)]
pub struct Stack<T: Clone> {
    snapshots: Vec<usize>,
    ops: Vec<StackOp<T>>,
    cache: Vec<T>
}

impl<T: Clone> Stack<T> {
    pub fn new() -> Self {
        Stack {
            ops: vec![],
            cache: vec![],
            snapshots: vec![]
        }
    }

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

    pub fn peek(&self) -> Option<&T> {
        self.cache.last()
    }

    pub fn push(&mut self, elem: T) {
        self.ops.push(StackOp::Push(elem.clone()));
        self.cache.push(elem);
    }

    pub fn pop(&mut self) -> Option<T> {
        self.ops.push(StackOp::Pop());
        self.cache.pop()
    }

    pub fn snapshot(&mut self) {
        self.snapshots.push(self.ops.len());
    }

    pub fn backtrack(&mut self) {
        match self.snapshots.pop() {
            Some(index) => {
                self.ops.truncate(index);
                self.recache();
            }
            None => {}
        }
    }

    fn recache(&mut self) {
        self.cache.clear();
        for op in self.ops.iter() {
            match op {
                &StackOp::Push(ref elem) => {
                    self.cache.push(elem.clone());
                },
                &StackOp::Pop() => {
                    self.cache.pop();
                }
            }
        }
    }
}

#[derive(Debug)]
enum StackOp<T> {
    Push(T),
    Pop()
}

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

    #[test]
    fn stack_ops() {
        let mut stack = Stack::new();

        // []
        assert!(stack.is_empty());
        assert_eq!(stack.peek(), None);
        assert_eq!(stack.pop(), None);

        // [0]
        stack.push(0);
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&0));

        // [0, 1]
        stack.push(1);
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&1));

        // [0]
        assert_eq!(stack.pop(), Some(1));
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&0));

        // [0, 2]
        stack.push(2);
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&2));

        // [0, 2, 3]
        stack.push(3);
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&3));

        // [0, 2]
        assert_eq!(stack.pop(), Some(3));
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&2));

        // Take a snapshot of the current stack
        stack.snapshot();

        // [0]
        assert_eq!(stack.pop(), Some(2));
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&0));

        // []
        assert_eq!(stack.pop(), Some(0));
        assert!(stack.is_empty());
        assert_eq!(stack.peek(), None);
        assert_eq!(stack.pop(), None);

        // Test backtracking
        // [0, 2]
        stack.backtrack();
        assert_eq!(stack.peek(), Some(&2));
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use toml;

#[derive(Debug, RustcDecodable)]
pub struct ModuleOpts {
    meta: MetaOpts,
    options: OptionsOpts
}

impl ModuleOpts {
    pub fn load(path: String) -> Result<ModuleOpts, &'static str> {
        let mut mod_string = String::new();
        let mut file = match File::open(&path) {
            Ok(file) => file,
            Err(_) => {
                return Err("Could not load config file")
            }
        };
        file.read_to_string(&mut mod_string)
        .unwrap_or_else(|e| panic!("Unrecoverable error while reading config: {}", e));

        let mut t_parser = toml::Parser::new(&mod_string);
        let tml = t_parser.parse();

        if tml.is_none() {
            for err in &t_parser.errors {
                let (loline, locol) = t_parser.to_linecol(err.lo);
                let (hiline, hicol) = t_parser.to_linecol(err.hi);
                println!("{}:{}:{}-{}:{} error: {}",
                         path, loline, locol, hiline, hicol, err.desc);
            }
            panic!("Unrecoverable error while parsing module config");

        }
        let module_opts = toml::Value::Table(tml.unwrap());

        Ok(toml::decode(module_opts).unwrap())
    }
}

#[derive(Debug, RustcDecodable)]
pub struct MetaOpts {
    name: String,
    version: String,
    author: String,
    license: String
}

#[derive(Debug, RustcDecodable)]
pub struct OptionsOpts {
    strip_whitespace: Option<bool>,
    core: Option<String>
}

pub struct Module<'a> {
    path: &'a Path, // Sub paths are determined relative to this one
    options: Option<ModuleOpts>
}

impl<'b> Module<'b> {
    pub fn new(path:&'b Path) -> Module {
        Module {
            path: path,
            options: None
        }
    }

    pub fn get_opts(&'b mut self) -> &'b ModuleOpts {
        match self.options {
            Some(ref opts) => opts,
            None => {
                self.options = Some(ModuleOpts::load(self.path.to_str().unwrap().to_string()).unwrap());
                self.get_opts()
            }
        }
    }
}
<commit_msg>Made module struct properties public (they're immutable, shouldn't be an issue<commit_after>use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use toml;

#[derive(Debug, RustcDecodable)]
pub struct ModuleOpts {
    meta: MetaOpts,
    options: OptionsOpts
}

impl ModuleOpts {
    pub fn load(path: String) -> Result<ModuleOpts, &'static str> {
        let mut mod_string = String::new();
        let mut file = match File::open(&path) {
            Ok(file) => file,
            Err(_) => {
                return Err("Could not load config file")
            }
        };
        file.read_to_string(&mut mod_string)
        .unwrap_or_else(|e| panic!("Unrecoverable error while reading config: {}", e));

        let mut t_parser = toml::Parser::new(&mod_string);
        let tml = t_parser.parse();

        if tml.is_none() {
            for err in &t_parser.errors {
                let (loline, locol) = t_parser.to_linecol(err.lo);
                let (hiline, hicol) = t_parser.to_linecol(err.hi);
                println!("{}:{}:{}-{}:{} error: {}",
                         path, loline, locol, hiline, hicol, err.desc);
            }
            panic!("Unrecoverable error while parsing module config");

        }
        let module_opts = toml::Value::Table(tml.unwrap());

        Ok(toml::decode(module_opts).unwrap())
    }
}

#[derive(Debug, RustcDecodable)]
pub struct MetaOpts {
    pub name: String,
    pub version: String,
    pub author: String,
    pub license: String
}

#[derive(Debug, RustcDecodable)]
pub struct OptionsOpts {
    pub strip_whitespace: Option<bool>,
    pub core: Option<String>
}

pub struct Module<'a> {
    path: &'a Path, // Sub paths are determined relative to this one
    options: Option<ModuleOpts>
}

impl<'b> Module<'b> {
    pub fn new(path:&'b Path) -> Module {
        Module {
            path: path,
            options: None
        }
    }

    pub fn get_opts(&'b mut self) -> &'b ModuleOpts {
        match self.options {
            Some(ref opts) => opts,
            None => {
                self.options = Some(ModuleOpts::load(self.path.to_str().unwrap().to_string()).unwrap());
                self.get_opts()
            }
        }
    }
}
<|endoftext|>


<commit_before>//! The data that we will serialize and deserialize.

use super::query::DepGraphQuery;
use super::{DepKind, DepNode, DepNodeIndex};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::{Lock, Lrc};
use rustc_index::vec::{Idx, IndexVec};
use rustc_serialize::opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize};
use rustc_serialize::{Decodable, Decoder, Encodable};
use smallvec::SmallVec;
use std::convert::TryInto;

// The maximum value of `SerializedDepNodeIndex` leaves the upper two bits
// unused so that we can store multiple index types in `CompressedHybridIndex`,
// and use those bits to encode which index type it contains.
rustc_index::newtype_index! {
    pub struct SerializedDepNodeIndex {
        MAX = 0x7FFF_FFFF
    }
}

/// Data for use when recompiling the **current crate**.
#[derive(Debug)]
pub struct SerializedDepGraph<K: DepKind> {
    /// The set of all DepNodes in the graph
    pub nodes: IndexVec<SerializedDepNodeIndex, DepNode<K>>,
    /// The set of all Fingerprints in the graph. Each Fingerprint corresponds to
    /// the DepNode at the same index in the nodes vector.
    pub fingerprints: IndexVec<SerializedDepNodeIndex, Fingerprint>,
    /// For each DepNode, stores the list of edges originating from that
    /// DepNode. Encoded as a [start, end) pair indexing into edge_list_data,
    /// which holds the actual DepNodeIndices of the target nodes.
    pub edge_list_indices: IndexVec<SerializedDepNodeIndex, (u32, u32)>,
    /// A flattened list of all edge targets in the graph. Edge sources are
    /// implicit in edge_list_indices.
    pub edge_list_data: Vec<SerializedDepNodeIndex>,
}

impl<K: DepKind> Default for SerializedDepGraph<K> {
    fn default() -> Self {
        SerializedDepGraph {
            nodes: Default::default(),
            fingerprints: Default::default(),
            edge_list_indices: Default::default(),
            edge_list_data: Default::default(),
        }
    }
}

impl<K: DepKind> SerializedDepGraph<K> {
    #[inline]
    pub fn edge_targets_from(&self, source: SerializedDepNodeIndex) -> &[SerializedDepNodeIndex] {
        let targets = self.edge_list_indices[source];
        &self.edge_list_data[targets.0 as usize..targets.1 as usize]
    }
}

impl<'a, K: DepKind + Decodable<opaque::Decoder<'a>>> Decodable<opaque::Decoder<'a>>
    for SerializedDepGraph<K>
{
    #[instrument(skip(d))]
    fn decode(d: &mut opaque::Decoder<'a>) -> Result<SerializedDepGraph<K>, String> {
        let position = d.position();

        // The last 16 bytes are the node count and edge count.
        debug!("position: {:?}", d.position());
        d.set_position(d.data.len() - 2 * IntEncodedWithFixedSize::ENCODED_SIZE);
        debug!("position: {:?}", d.position());

        let node_count = IntEncodedWithFixedSize::decode(d)?.0 as usize;
        let edge_count = IntEncodedWithFixedSize::decode(d)?.0 as usize;
        debug!(?node_count, ?edge_count);

        debug!("position: {:?}", d.position());
        d.set_position(position);
        debug!("position: {:?}", d.position());

        let mut nodes = IndexVec::with_capacity(node_count);
        let mut fingerprints = IndexVec::with_capacity(node_count);
        let mut edge_list_indices = IndexVec::with_capacity(node_count);
        let mut edge_list_data = Vec::with_capacity(edge_count);

        for _index in 0..node_count {
            d.read_struct("NodeInfo", 3, |d| {
                let dep_node: DepNode<K> = d.read_struct_field("node", 0, Decodable::decode)?;
                let _i: SerializedDepNodeIndex = nodes.push(dep_node);
                debug_assert_eq!(_i.index(), _index);

                let fingerprint: Fingerprint =
                    d.read_struct_field("fingerprint", 1, Decodable::decode)?;
                let _i: SerializedDepNodeIndex = fingerprints.push(fingerprint);
                debug_assert_eq!(_i.index(), _index);

                d.read_struct_field("edges", 2, |d| {
                    d.read_seq(|d, len| {
                        let start = edge_list_data.len().try_into().unwrap();
                        for e in 0..len {
                            let edge = d.read_seq_elt(e, Decodable::decode)?;
                            edge_list_data.push(edge);
                        }
                        let end = edge_list_data.len().try_into().unwrap();
                        let _i: SerializedDepNodeIndex = edge_list_indices.push((start, end));
                        debug_assert_eq!(_i.index(), _index);
                        Ok(())
                    })
                })
            })?;
        }

        Ok(SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data })
    }
}

#[derive(Debug, Encodable, Decodable)]
pub struct NodeInfo<K: DepKind> {
    node: DepNode<K>,
    fingerprint: Fingerprint,
    edges: SmallVec<[DepNodeIndex; 8]>,
}

struct Stat<K: DepKind> {
    kind: K,
    node_counter: u64,
    edge_counter: u64,
}

struct Stats<K: DepKind> {
    stats: FxHashMap<K, Stat<K>>,
    total_node_count: usize,
    total_edge_count: usize,
}

#[instrument(skip(encoder, _record_graph, record_stats))]
fn encode_node<K: DepKind>(
    encoder: &mut FileEncoder,
    _index: DepNodeIndex,
    node: &NodeInfo<K>,
    _record_graph: &Option<Lrc<Lock<DepGraphQuery<K>>>>,
    record_stats: &Option<Lrc<Lock<Stats<K>>>>,
) -> FileEncodeResult {
    #[cfg(debug_assertions)]
    if let Some(record_graph) = &_record_graph {
        // Do not ICE when a query is called from within `with_query`.
        if let Some(record_graph) = &mut record_graph.try_lock() {
            record_graph.push(_index, node.node, &node.edges);
        }
    }

    if let Some(record_stats) = &record_stats {
        let mut stats = record_stats.lock();
        let kind = node.node.kind;
        let edge_count = node.edges.len();

        let stat =
            stats.stats.entry(kind).or_insert(Stat { kind, node_counter: 0, edge_counter: 0 });
        stat.node_counter += 1;
        stat.edge_counter += edge_count as u64;
        stats.total_node_count += 1;
        stats.total_edge_count += edge_count;
    }

    debug!(?_index, ?node);
    node.encode(encoder)
}

fn encode_counts(
    mut encoder: FileEncoder,
    node_count: usize,
    edge_count: usize,
) -> FileEncodeResult {
    let node_count = node_count.try_into().unwrap();
    let edge_count = edge_count.try_into().unwrap();

    debug!(?node_count, ?edge_count);
    debug!("position: {:?}", encoder.position());
    IntEncodedWithFixedSize(node_count).encode(&mut encoder)?;
    IntEncodedWithFixedSize(edge_count).encode(&mut encoder)?;
    debug!("position: {:?}", encoder.position());
    // Drop the encoder so that nothing is written after the counts.
    encoder.flush()
}

pub struct GraphEncoder<K: DepKind> {
    status: Lock<(FileEncoder, DepNodeIndex, usize, FileEncodeResult)>,
    record_graph: Option<Lrc<Lock<DepGraphQuery<K>>>>,
    record_stats: Option<Lrc<Lock<Stats<K>>>>,
}

impl<K: DepKind + Encodable<FileEncoder>> GraphEncoder<K> {
    pub fn new(
        encoder: FileEncoder,
        prev_node_count: usize,
        record_graph: bool,
        record_stats: bool,
    ) -> Self {
        let record_graph = if cfg!(debug_assertions) && record_graph {
            Some(Lrc::new(Lock::new(DepGraphQuery::new(prev_node_count))))
        } else {
            None
        };
        let record_stats = if record_stats {
            Some(Lrc::new(Lock::new(Stats {
                stats: FxHashMap::default(),
                total_node_count: 0,
                total_edge_count: 0,
            })))
        } else {
            None
        };
        let status = Lock::new((encoder, DepNodeIndex::new(0), 0, Ok(())));
        GraphEncoder { status, record_graph, record_stats }
    }

    pub(crate) fn with_query(&self, f: impl Fn(&DepGraphQuery<K>)) {
        if let Some(record_graph) = &self.record_graph {
            f(&record_graph.lock())
        }
    }

    pub(crate) fn print_incremental_info(
        &self,
        total_read_count: u64,
        total_duplicate_read_count: u64,
    ) {
        if let Some(record_stats) = &self.record_stats {
            let record_stats = record_stats.lock();

            let mut stats: Vec<_> = record_stats.stats.values().collect();
            stats.sort_by_key(|s| -(s.node_counter as i64));

            const SEPARATOR: &str = "[incremental] --------------------------------\
                                     ----------------------------------------------\
                                     ------------";

            eprintln!("[incremental]");
            eprintln!("[incremental] DepGraph Statistics");
            eprintln!("{}", SEPARATOR);
            eprintln!("[incremental]");
            eprintln!("[incremental] Total Node Count: {}", record_stats.total_node_count);
            eprintln!("[incremental] Total Edge Count: {}", record_stats.total_edge_count);

            if cfg!(debug_assertions) {
                eprintln!("[incremental] Total Edge Reads: {}", total_read_count);
                eprintln!(
                    "[incremental] Total Duplicate Edge Reads: {}",
                    total_duplicate_read_count
                );
            }

            eprintln!("[incremental]");
            eprintln!(
                "[incremental]  {:<36}| {:<17}| {:<12}| {:<17}|",
                "Node Kind", "Node Frequency", "Node Count", "Avg. Edge Count"
            );
            eprintln!("{}", SEPARATOR);

            for stat in stats {
                let node_kind_ratio =
                    (100.0 * (stat.node_counter as f64)) / (record_stats.total_node_count as f64);
                let node_kind_avg_edges = (stat.edge_counter as f64) / (stat.node_counter as f64);

                eprintln!(
                    "[incremental]  {:<36}|{:>16.1}% |{:>12} |{:>17.1} |",
                    format!("{:?}", stat.kind),
                    node_kind_ratio,
                    stat.node_counter,
                    node_kind_avg_edges,
                );
            }

            eprintln!("{}", SEPARATOR);
            eprintln!("[incremental]");
        }
    }

    pub(crate) fn send(
        &self,
        node: DepNode<K>,
        fingerprint: Fingerprint,
        edges: SmallVec<[DepNodeIndex; 8]>,
    ) -> DepNodeIndex {
        let &mut (ref mut encoder, ref mut next_index, ref mut edge_count, ref mut result) =
            &mut *self.status.lock();
        let index = next_index.clone();
        next_index.increment_by(1);
        *edge_count += edges.len();
        *result = std::mem::replace(result, Ok(())).and_then(|()| {
            let node = NodeInfo { node, fingerprint, edges };
            encode_node(encoder, index, &node, &self.record_graph, &self.record_stats)
        });
        index
    }

    pub fn finish(self) -> FileEncodeResult {
        let (encoder, node_count, edge_count, result) = self.status.into_inner();
        let () = result?;
        let node_count = node_count.index();

        encode_counts(encoder, node_count, edge_count)
    }
}
<commit_msg>Simplify tracking the encoder state.<commit_after>//! The data that we will serialize and deserialize.

use super::query::DepGraphQuery;
use super::{DepKind, DepNode, DepNodeIndex};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lock;
use rustc_index::vec::{Idx, IndexVec};
use rustc_serialize::opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize};
use rustc_serialize::{Decodable, Decoder, Encodable};
use smallvec::SmallVec;
use std::convert::TryInto;

// The maximum value of `SerializedDepNodeIndex` leaves the upper two bits
// unused so that we can store multiple index types in `CompressedHybridIndex`,
// and use those bits to encode which index type it contains.
rustc_index::newtype_index! {
    pub struct SerializedDepNodeIndex {
        MAX = 0x7FFF_FFFF
    }
}

/// Data for use when recompiling the **current crate**.
#[derive(Debug)]
pub struct SerializedDepGraph<K: DepKind> {
    /// The set of all DepNodes in the graph
    pub nodes: IndexVec<SerializedDepNodeIndex, DepNode<K>>,
    /// The set of all Fingerprints in the graph. Each Fingerprint corresponds to
    /// the DepNode at the same index in the nodes vector.
    pub fingerprints: IndexVec<SerializedDepNodeIndex, Fingerprint>,
    /// For each DepNode, stores the list of edges originating from that
    /// DepNode. Encoded as a [start, end) pair indexing into edge_list_data,
    /// which holds the actual DepNodeIndices of the target nodes.
    pub edge_list_indices: IndexVec<SerializedDepNodeIndex, (u32, u32)>,
    /// A flattened list of all edge targets in the graph. Edge sources are
    /// implicit in edge_list_indices.
    pub edge_list_data: Vec<SerializedDepNodeIndex>,
}

impl<K: DepKind> Default for SerializedDepGraph<K> {
    fn default() -> Self {
        SerializedDepGraph {
            nodes: Default::default(),
            fingerprints: Default::default(),
            edge_list_indices: Default::default(),
            edge_list_data: Default::default(),
        }
    }
}

impl<K: DepKind> SerializedDepGraph<K> {
    #[inline]
    pub fn edge_targets_from(&self, source: SerializedDepNodeIndex) -> &[SerializedDepNodeIndex] {
        let targets = self.edge_list_indices[source];
        &self.edge_list_data[targets.0 as usize..targets.1 as usize]
    }
}

impl<'a, K: DepKind + Decodable<opaque::Decoder<'a>>> Decodable<opaque::Decoder<'a>>
    for SerializedDepGraph<K>
{
    #[instrument(skip(d))]
    fn decode(d: &mut opaque::Decoder<'a>) -> Result<SerializedDepGraph<K>, String> {
        let position = d.position();

        // The last 16 bytes are the node count and edge count.
        debug!("position: {:?}", d.position());
        d.set_position(d.data.len() - 2 * IntEncodedWithFixedSize::ENCODED_SIZE);
        debug!("position: {:?}", d.position());

        let node_count = IntEncodedWithFixedSize::decode(d)?.0 as usize;
        let edge_count = IntEncodedWithFixedSize::decode(d)?.0 as usize;
        debug!(?node_count, ?edge_count);

        debug!("position: {:?}", d.position());
        d.set_position(position);
        debug!("position: {:?}", d.position());

        let mut nodes = IndexVec::with_capacity(node_count);
        let mut fingerprints = IndexVec::with_capacity(node_count);
        let mut edge_list_indices = IndexVec::with_capacity(node_count);
        let mut edge_list_data = Vec::with_capacity(edge_count);

        for _index in 0..node_count {
            d.read_struct("NodeInfo", 3, |d| {
                let dep_node: DepNode<K> = d.read_struct_field("node", 0, Decodable::decode)?;
                let _i: SerializedDepNodeIndex = nodes.push(dep_node);
                debug_assert_eq!(_i.index(), _index);

                let fingerprint: Fingerprint =
                    d.read_struct_field("fingerprint", 1, Decodable::decode)?;
                let _i: SerializedDepNodeIndex = fingerprints.push(fingerprint);
                debug_assert_eq!(_i.index(), _index);

                d.read_struct_field("edges", 2, |d| {
                    d.read_seq(|d, len| {
                        let start = edge_list_data.len().try_into().unwrap();
                        for e in 0..len {
                            let edge = d.read_seq_elt(e, Decodable::decode)?;
                            edge_list_data.push(edge);
                        }
                        let end = edge_list_data.len().try_into().unwrap();
                        let _i: SerializedDepNodeIndex = edge_list_indices.push((start, end));
                        debug_assert_eq!(_i.index(), _index);
                        Ok(())
                    })
                })
            })?;
        }

        Ok(SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data })
    }
}

#[derive(Debug, Encodable, Decodable)]
pub struct NodeInfo<K: DepKind> {
    node: DepNode<K>,
    fingerprint: Fingerprint,
    edges: SmallVec<[DepNodeIndex; 8]>,
}

struct Stat<K: DepKind> {
    kind: K,
    node_counter: u64,
    edge_counter: u64,
}

struct EncodingStatus<K: DepKind> {
    encoder: FileEncoder,
    total_node_count: usize,
    total_edge_count: usize,
    result: FileEncodeResult,
    stats: Option<FxHashMap<K, Stat<K>>>,
}

impl<K: DepKind> EncodingStatus<K> {
    fn new(encoder: FileEncoder, record_stats: bool) -> Self {
        Self {
            encoder,
            total_edge_count: 0,
            total_node_count: 0,
            result: Ok(()),
            stats: if record_stats { Some(FxHashMap::default()) } else { None },
        }
    }

    #[instrument(skip(self, _record_graph))]
    fn encode_node(
        &mut self,
        node: &NodeInfo<K>,
        _record_graph: &Option<Lock<DepGraphQuery<K>>>,
    ) -> DepNodeIndex {
        let index = DepNodeIndex::new(self.total_node_count);
        self.total_node_count += 1;

        let edge_count = node.edges.len();
        self.total_edge_count += edge_count;

        #[cfg(debug_assertions)]
        if let Some(record_graph) = &_record_graph {
            // Do not ICE when a query is called from within `with_query`.
            if let Some(record_graph) = &mut record_graph.try_lock() {
                record_graph.push(index, node.node, &node.edges);
            }
        }

        if let Some(stats) = &mut self.stats {
            let kind = node.node.kind;

            let stat = stats.entry(kind).or_insert(Stat { kind, node_counter: 0, edge_counter: 0 });
            stat.node_counter += 1;
            stat.edge_counter += edge_count as u64;
        }

        debug!(?index, ?node);
        let encoder = &mut self.encoder;
        self.result =
            std::mem::replace(&mut self.result, Ok(())).and_then(|()| node.encode(encoder));
        index
    }

    fn finish(self) -> FileEncodeResult {
        let Self { mut encoder, total_node_count, total_edge_count, result, stats: _ } = self;
        let () = result?;

        let node_count = total_node_count.try_into().unwrap();
        let edge_count = total_edge_count.try_into().unwrap();

        debug!(?node_count, ?edge_count);
        debug!("position: {:?}", encoder.position());
        IntEncodedWithFixedSize(node_count).encode(&mut encoder)?;
        IntEncodedWithFixedSize(edge_count).encode(&mut encoder)?;
        debug!("position: {:?}", encoder.position());
        // Drop the encoder so that nothing is written after the counts.
        encoder.flush()
    }
}

pub struct GraphEncoder<K: DepKind> {
    status: Lock<EncodingStatus<K>>,
    record_graph: Option<Lock<DepGraphQuery<K>>>,
}

impl<K: DepKind + Encodable<FileEncoder>> GraphEncoder<K> {
    pub fn new(
        encoder: FileEncoder,
        prev_node_count: usize,
        record_graph: bool,
        record_stats: bool,
    ) -> Self {
        let record_graph = if cfg!(debug_assertions) && record_graph {
            Some(Lock::new(DepGraphQuery::new(prev_node_count)))
        } else {
            None
        };
        let status = Lock::new(EncodingStatus::new(encoder, record_stats));
        GraphEncoder { status, record_graph }
    }

    pub(crate) fn with_query(&self, f: impl Fn(&DepGraphQuery<K>)) {
        if let Some(record_graph) = &self.record_graph {
            f(&record_graph.lock())
        }
    }

    pub(crate) fn print_incremental_info(
        &self,
        total_read_count: u64,
        total_duplicate_read_count: u64,
    ) {
        let status = self.status.lock();
        if let Some(record_stats) = &status.stats {
            let mut stats: Vec<_> = record_stats.values().collect();
            stats.sort_by_key(|s| -(s.node_counter as i64));

            const SEPARATOR: &str = "[incremental] --------------------------------\
                                     ----------------------------------------------\
                                     ------------";

            eprintln!("[incremental]");
            eprintln!("[incremental] DepGraph Statistics");
            eprintln!("{}", SEPARATOR);
            eprintln!("[incremental]");
            eprintln!("[incremental] Total Node Count: {}", status.total_node_count);
            eprintln!("[incremental] Total Edge Count: {}", status.total_edge_count);

            if cfg!(debug_assertions) {
                eprintln!("[incremental] Total Edge Reads: {}", total_read_count);
                eprintln!(
                    "[incremental] Total Duplicate Edge Reads: {}",
                    total_duplicate_read_count
                );
            }

            eprintln!("[incremental]");
            eprintln!(
                "[incremental]  {:<36}| {:<17}| {:<12}| {:<17}|",
                "Node Kind", "Node Frequency", "Node Count", "Avg. Edge Count"
            );
            eprintln!("{}", SEPARATOR);

            for stat in stats {
                let node_kind_ratio =
                    (100.0 * (stat.node_counter as f64)) / (status.total_node_count as f64);
                let node_kind_avg_edges = (stat.edge_counter as f64) / (stat.node_counter as f64);

                eprintln!(
                    "[incremental]  {:<36}|{:>16.1}% |{:>12} |{:>17.1} |",
                    format!("{:?}", stat.kind),
                    node_kind_ratio,
                    stat.node_counter,
                    node_kind_avg_edges,
                );
            }

            eprintln!("{}", SEPARATOR);
            eprintln!("[incremental]");
        }
    }

    pub(crate) fn send(
        &self,
        node: DepNode<K>,
        fingerprint: Fingerprint,
        edges: SmallVec<[DepNodeIndex; 8]>,
    ) -> DepNodeIndex {
        let node = NodeInfo { node, fingerprint, edges };
        self.status.lock().encode_node(&node, &self.record_graph)
    }

    pub fn finish(self) -> FileEncodeResult {
        self.status.into_inner().finish()
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use core::Message;
use reflect::FieldDescriptor;
use reflect::EnumValueDescriptor;
use descriptor::*;

fn print_bytes_to(bytes: &[u8], buf: &mut String) {
    buf.push('"');
    for &b in bytes.iter() {
        if b < 0x20 || b >= 0x7f {
            buf.push('\\');
            buf.push((b'0' + ((b >> 6) & 3)) as char);
            buf.push((b'0' + ((b >> 3) & 7)) as char);
            buf.push((b'0' + (b & 7)) as char);
        } else if b == b'"' {
            buf.push_str("\\\"");
        } else if b == b'\\' {
            buf.push_str("\\\\");
        } else {
            buf.push(b as char);
        }
    }
    buf.push('"');
}

fn print_str_to(s: &str, buf: &mut String) {
    // TODO: keep printable Unicode
    print_bytes_to(s.as_bytes(), buf);
}

fn do_indent(buf: &mut String, pretty: bool, indent: usize) {
    if pretty && indent > 0 {
        for _ in 0..indent {
            buf.push_str("  ");
        }
    }
}

// internal helper
impl FieldDescriptor {
    // len fo repeated field, or 1 or 0 for singular field
    fn len_field_x(&self, m: &Message) -> usize {
        if self.is_repeated() {
            self.len_field(m)
        } else {
            match self.has_field(m) {
                true => 1,
                false => 0,
            }
        }
    }

    // get item by index for repeated fields, or just field for singular fields

    fn get_rep_message_item_x<'a>(&self, m: &'a Message, index: usize) -> &'a Message {
        if self.is_repeated() {
            self.get_rep_message_item(m, index)
        } else {
            assert_eq!(0, index);
            self.get_message(m)
        }
    }

    fn get_rep_enum_item_x(&self, m: &Message, index: usize) -> &'static EnumValueDescriptor {
        if self.is_repeated() {
            self.get_rep_enum_item(m, index)
        } else {
            assert_eq!(0, index);
            self.get_enum(m)
        }
    }

    fn get_rep_str_item_x<'a>(&self, m: &'a Message, index: usize) -> &'a str {
        if self.is_repeated() {
            self.get_rep_str_item(m, index)
        } else {
            assert_eq!(0, index);
            self.get_str(m)
        }
    }

    fn get_rep_bytes_item_x<'a>(&self, m: &'a Message, index: usize) -> &'a [u8] {
        if self.is_repeated() {
            self.get_rep_bytes_item(m, index)
        } else {
            assert_eq!(0, index);
            self.get_bytes(m)
        }
    }

    fn get_rep_i32_item_x(&self, m: &Message, index: usize) -> i32 {
        if self.is_repeated() {
            self.get_rep_i32(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_i32(m)
        }
    }

    fn get_rep_u32_item_x(&self, m: &Message, index: usize) -> u32 {
        if self.is_repeated() {
            self.get_rep_u32(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_u32(m)
        }
    }

    fn get_rep_i64_item_x(&self, m: &Message, index: usize) -> i64 {
        if self.is_repeated() {
            self.get_rep_i64(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_i64(m)
        }
    }

    fn get_rep_u64_item_x(&self, m: &Message, index: usize) -> u64 {
        if self.is_repeated() {
            self.get_rep_u64(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_u64(m)
        }
    }

    fn get_rep_bool_item_x(&self, m: &Message, index: usize) -> bool {
        if self.is_repeated() {
            self.get_rep_bool(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_bool(m)
        }
    }

    fn get_rep_f32_item_x(&self, m: &Message, index: usize) -> f32 {
        if self.is_repeated() {
            self.get_rep_f32(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_f32(m)
        }
    }

    fn get_rep_f64_item_x(&self, m: &Message, index: usize) -> f64 {
        if self.is_repeated() {
            self.get_rep_f64(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_f64(m)
        }
    }

}

fn print_to_internal(m: &Message, buf: &mut String, pretty: bool, indent: usize) {
    let d = m.descriptor();
    let mut first = true;
    for f in d.fields().iter() {
        for i in 0..f.len_field_x(m) {
            if !first && !pretty {
                buf.push_str(" ");
            }
            do_indent(buf, pretty, indent);
            first = false;
            buf.push_str(f.name());
            match f.proto().get_field_type() {
                FieldDescriptorProto_Type::TYPE_MESSAGE => {
                    buf.push_str(" {");
                    if pretty {
                        buf.push_str("\n");
                    }
                    print_to_internal(f.get_rep_message_item_x(m, i), buf, pretty, indent+1);
                    do_indent(buf, pretty, indent);
                    buf.push_str("}");
                },
                FieldDescriptorProto_Type::TYPE_ENUM => {
                    buf.push_str(": ");
                    buf.push_str(f.get_rep_enum_item_x(m, i).name());
                },
                FieldDescriptorProto_Type::TYPE_STRING => {
                    buf.push_str(": ");
                    print_str_to(f.get_rep_str_item_x(m, i), buf);
                },
                FieldDescriptorProto_Type::TYPE_BYTES => {
                    buf.push_str(": ");
                    print_bytes_to(f.get_rep_bytes_item_x(m, i), buf);
                },
                FieldDescriptorProto_Type::TYPE_INT32 |
                FieldDescriptorProto_Type::TYPE_SINT32 |
                FieldDescriptorProto_Type::TYPE_SFIXED32 => {
                    buf.push_str(": ");
                    buf.push_str(&f.get_rep_i32_item_x(m, i).to_string());
                },
                FieldDescriptorProto_Type::TYPE_INT64 |
                FieldDescriptorProto_Type::TYPE_SINT64 |
                FieldDescriptorProto_Type::TYPE_SFIXED64 => {
                    buf.push_str(": ");
                    buf.push_str(&f.get_rep_i64_item_x(m, i).to_string());
                },
                FieldDescriptorProto_Type::TYPE_UINT32 |
                FieldDescriptorProto_Type::TYPE_FIXED32 => {
                    buf.push_str(": ");
                    buf.push_str(&f.get_rep_u32_item_x(m, i).to_string());
                },
                FieldDescriptorProto_Type::TYPE_UINT64 |
                FieldDescriptorProto_Type::TYPE_FIXED64 => {
                    buf.push_str(": ");
                    buf.push_str(&f.get_rep_u64_item_x(m, i).to_string());
                },
                FieldDescriptorProto_Type::TYPE_BOOL => {
                    buf.push_str(": ");
                    buf.push_str(&f.get_rep_bool_item_x(m, i).to_string());
                },
                FieldDescriptorProto_Type::TYPE_FLOAT => {
                    buf.push_str(": ");
                    buf.push_str(&f.get_rep_f32_item_x(m, i).to_string());
                },
                FieldDescriptorProto_Type::TYPE_DOUBLE => {
                    buf.push_str(": ");
                    buf.push_str(&f.get_rep_f64_item_x(m, i).to_string());
                },
                FieldDescriptorProto_Type::TYPE_GROUP => {
                    buf.push_str(": <TYPE_GROUP>");
                }
            }
            if pretty {
                buf.push_str("\n");
            }
        }
    }

    // TODO: unknown fields
}

pub fn print_to(m: &Message, buf: &mut String) {
    print_to_internal(m, buf, false, 0)
}

fn print_to_string_internal(m: &Message, pretty: bool) -> String {
    let mut r = String::new();
    print_to_internal(m, &mut r, pretty, 0);
    r.to_string()
}

pub fn print_to_string(m: &Message) -> String {
    print_to_string_internal(m, false)
}

pub fn fmt(m: &Message, f: &mut fmt::Formatter) -> fmt::Result {
    let pretty = f.alternate();
    f.write_str(&print_to_string_internal(m, pretty))
}
<commit_msg>avoid string allocation when printing to text_format for primitive types<commit_after>use std::fmt;
use std::fmt::Write;
use core::Message;
use reflect::FieldDescriptor;
use reflect::EnumValueDescriptor;
use descriptor::*;

fn print_bytes_to(bytes: &[u8], buf: &mut String) {
    buf.push('"');
    for &b in bytes.iter() {
        if b < 0x20 || b >= 0x7f {
            buf.push('\\');
            buf.push((b'0' + ((b >> 6) & 3)) as char);
            buf.push((b'0' + ((b >> 3) & 7)) as char);
            buf.push((b'0' + (b & 7)) as char);
        } else if b == b'"' {
            buf.push_str("\\\"");
        } else if b == b'\\' {
            buf.push_str("\\\\");
        } else {
            buf.push(b as char);
        }
    }
    buf.push('"');
}

fn print_str_to(s: &str, buf: &mut String) {
    // TODO: keep printable Unicode
    print_bytes_to(s.as_bytes(), buf);
}

fn do_indent(buf: &mut String, pretty: bool, indent: usize) {
    if pretty && indent > 0 {
        for _ in 0..indent {
            buf.push_str("  ");
        }
    }
}

// internal helper
impl FieldDescriptor {
    // len fo repeated field, or 1 or 0 for singular field
    fn len_field_x(&self, m: &Message) -> usize {
        if self.is_repeated() {
            self.len_field(m)
        } else {
            match self.has_field(m) {
                true => 1,
                false => 0,
            }
        }
    }

    // get item by index for repeated fields, or just field for singular fields

    fn get_rep_message_item_x<'a>(&self, m: &'a Message, index: usize) -> &'a Message {
        if self.is_repeated() {
            self.get_rep_message_item(m, index)
        } else {
            assert_eq!(0, index);
            self.get_message(m)
        }
    }

    fn get_rep_enum_item_x(&self, m: &Message, index: usize) -> &'static EnumValueDescriptor {
        if self.is_repeated() {
            self.get_rep_enum_item(m, index)
        } else {
            assert_eq!(0, index);
            self.get_enum(m)
        }
    }

    fn get_rep_str_item_x<'a>(&self, m: &'a Message, index: usize) -> &'a str {
        if self.is_repeated() {
            self.get_rep_str_item(m, index)
        } else {
            assert_eq!(0, index);
            self.get_str(m)
        }
    }

    fn get_rep_bytes_item_x<'a>(&self, m: &'a Message, index: usize) -> &'a [u8] {
        if self.is_repeated() {
            self.get_rep_bytes_item(m, index)
        } else {
            assert_eq!(0, index);
            self.get_bytes(m)
        }
    }

    fn get_rep_i32_item_x(&self, m: &Message, index: usize) -> i32 {
        if self.is_repeated() {
            self.get_rep_i32(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_i32(m)
        }
    }

    fn get_rep_u32_item_x(&self, m: &Message, index: usize) -> u32 {
        if self.is_repeated() {
            self.get_rep_u32(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_u32(m)
        }
    }

    fn get_rep_i64_item_x(&self, m: &Message, index: usize) -> i64 {
        if self.is_repeated() {
            self.get_rep_i64(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_i64(m)
        }
    }

    fn get_rep_u64_item_x(&self, m: &Message, index: usize) -> u64 {
        if self.is_repeated() {
            self.get_rep_u64(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_u64(m)
        }
    }

    fn get_rep_bool_item_x(&self, m: &Message, index: usize) -> bool {
        if self.is_repeated() {
            self.get_rep_bool(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_bool(m)
        }
    }

    fn get_rep_f32_item_x(&self, m: &Message, index: usize) -> f32 {
        if self.is_repeated() {
            self.get_rep_f32(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_f32(m)
        }
    }

    fn get_rep_f64_item_x(&self, m: &Message, index: usize) -> f64 {
        if self.is_repeated() {
            self.get_rep_f64(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_f64(m)
        }
    }

}

#[allow(unused_must_use)] // because write!(..) to String need to to be checked
fn print_to_internal(m: &Message, buf: &mut String, pretty: bool, indent: usize) {
    let d = m.descriptor();
    let mut first = true;
    for f in d.fields().iter() {
        for i in 0..f.len_field_x(m) {
            if !first && !pretty {
                buf.push_str(" ");
            }
            do_indent(buf, pretty, indent);
            first = false;
            buf.push_str(f.name());
            match f.proto().get_field_type() {
                FieldDescriptorProto_Type::TYPE_MESSAGE => {
                    buf.push_str(" {");
                    if pretty {
                        buf.push_str("\n");
                    }
                    print_to_internal(f.get_rep_message_item_x(m, i), buf, pretty, indent+1);
                    do_indent(buf, pretty, indent);
                    buf.push_str("}");
                },
                FieldDescriptorProto_Type::TYPE_ENUM => {
                    buf.push_str(": ");
                    buf.push_str(f.get_rep_enum_item_x(m, i).name());
                },
                FieldDescriptorProto_Type::TYPE_STRING => {
                    buf.push_str(": ");
                    print_str_to(f.get_rep_str_item_x(m, i), buf);
                },
                FieldDescriptorProto_Type::TYPE_BYTES => {
                    buf.push_str(": ");
                    print_bytes_to(f.get_rep_bytes_item_x(m, i), buf);
                },
                FieldDescriptorProto_Type::TYPE_INT32 |
                FieldDescriptorProto_Type::TYPE_SINT32 |
                FieldDescriptorProto_Type::TYPE_SFIXED32 => {
                    write!(buf, ": {}", f.get_rep_i32_item_x(m, i));
                },
                FieldDescriptorProto_Type::TYPE_INT64 |
                FieldDescriptorProto_Type::TYPE_SINT64 |
                FieldDescriptorProto_Type::TYPE_SFIXED64 => {
                    write!(buf, ": {}", f.get_rep_i64_item_x(m, i));
                },
                FieldDescriptorProto_Type::TYPE_UINT32 |
                FieldDescriptorProto_Type::TYPE_FIXED32 => {
                    write!(buf, ": {}", f.get_rep_u32_item_x(m, i));
                },
                FieldDescriptorProto_Type::TYPE_UINT64 |
                FieldDescriptorProto_Type::TYPE_FIXED64 => {
                    write!(buf, ": {}", f.get_rep_u64_item_x(m, i));
                },
                FieldDescriptorProto_Type::TYPE_BOOL => {
                    write!(buf, ": {}", f.get_rep_bool_item_x(m, i));
                },
                FieldDescriptorProto_Type::TYPE_FLOAT => {
                    write!(buf, ": {}", f.get_rep_f32_item_x(m, i));
                },
                FieldDescriptorProto_Type::TYPE_DOUBLE => {
                    write!(buf, ": {}", f.get_rep_f64_item_x(m, i));
                },
                FieldDescriptorProto_Type::TYPE_GROUP => {
                    buf.push_str(": <TYPE_GROUP>");
                }
            }
            if pretty {
                buf.push_str("\n");
            }
        }
    }

    // TODO: unknown fields
}

pub fn print_to(m: &Message, buf: &mut String) {
    print_to_internal(m, buf, false, 0)
}

fn print_to_string_internal(m: &Message, pretty: bool) -> String {
    let mut r = String::new();
    print_to_internal(m, &mut r, pretty, 0);
    r.to_string()
}

pub fn print_to_string(m: &Message) -> String {
    print_to_string_internal(m, false)
}

pub fn fmt(m: &Message, f: &mut fmt::Formatter) -> fmt::Result {
    let pretty = f.alternate();
    f.write_str(&print_to_string_internal(m, pretty))
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

#[doc(hidden)];

use libc::{c_char, c_void, intptr_t, uintptr_t};
use ptr::mut_null;
use repr::BoxRepr;
use sys::TypeDesc;
use cast::transmute;

#[cfg(notest)] use ptr::to_unsafe_ptr;

/**
 * Runtime structures
 *
 * NB: These must match the representation in the C++ runtime.
 */

type DropGlue<'self> = &'self fn(**TypeDesc, *c_void);
type FreeGlue<'self> = &'self fn(**TypeDesc, *c_void);

type TaskID = uintptr_t;

struct StackSegment { priv opaque: () }
struct Scheduler { priv opaque: () }
struct SchedulerLoop { priv opaque: () }
struct Kernel { priv opaque: () }
struct Env { priv opaque: () }
struct AllocHeader { priv opaque: () }
struct MemoryRegion { priv opaque: () }

#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
struct Registers {
    data: [u32, ..16]
}

#[cfg(target_arch="mips")]
struct Registers {
    data: [u32, ..32]
}

#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
#[cfg(target_arch="mips")]
struct Context {
    regs: Registers,
    next: *Context,
    pad: [u32, ..3]
}

#[cfg(target_arch="x86_64")]
struct Registers {
    data: [u64, ..22]
}

#[cfg(target_arch="x86_64")]
struct Context {
    regs: Registers,
    next: *Context,
    pad: uintptr_t
}

struct BoxedRegion {
    env: *Env,
    backing_region: *MemoryRegion,
    live_allocs: *BoxRepr
}

#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
#[cfg(target_arch="mips")]
struct Task {
    // Public fields
    refcount: intptr_t,                 // 0
    id: TaskID,                         // 4
    pad: [u32, ..2],                    // 8
    ctx: Context,                       // 16
    stack_segment: *StackSegment,       // 96
    runtime_sp: uintptr_t,              // 100
    scheduler: *Scheduler,              // 104
    scheduler_loop: *SchedulerLoop,     // 108

    // Fields known only to the runtime
    kernel: *Kernel,                    // 112
    name: *c_char,                      // 116
    list_index: i32,                    // 120
    boxed_region: BoxedRegion           // 128
}

#[cfg(target_arch="x86_64")]
struct Task {
    // Public fields
    refcount: intptr_t,
    id: TaskID,
    ctx: Context,
    stack_segment: *StackSegment,
    runtime_sp: uintptr_t,
    scheduler: *Scheduler,
    scheduler_loop: *SchedulerLoop,

    // Fields known only to the runtime
    kernel: *Kernel,
    name: *c_char,
    list_index: i32,
    boxed_region: BoxedRegion
}

/*
 * Box annihilation
 *
 * This runs at task death to free all boxes.
 */

struct AnnihilateStats {
    n_total_boxes: uint,
    n_unique_boxes: uint,
    n_bytes_freed: uint
}

unsafe fn each_live_alloc(f: &fn(box: *mut BoxRepr, uniq: bool) -> bool) {
    use managed;

    let task: *Task = transmute(rustrt::rust_get_task());
    let box = (*task).boxed_region.live_allocs;
    let mut box: *mut BoxRepr = transmute(copy box);
    while box != mut_null() {
        let next = transmute(copy (*box).header.next);
        let uniq =
            (*box).header.ref_count == managed::raw::RC_MANAGED_UNIQUE;

        if ! f(box, uniq) {
            break
        }

        box = next
    }
}

#[cfg(unix)]
fn debug_mem() -> bool {
    ::rt::env::get().debug_mem
}

#[cfg(windows)]
fn debug_mem() -> bool {
    false
}

/// Destroys all managed memory (i.e. @ boxes) held by the current task.
#[cfg(notest)]
#[lang="annihilate"]
pub unsafe fn annihilate() {
    use unstable::lang::local_free;
    use io::WriterUtil;
    use io;
    use libc;
    use sys;
    use managed;

    let mut stats = AnnihilateStats {
        n_total_boxes: 0,
        n_unique_boxes: 0,
        n_bytes_freed: 0
    };

    // Pass 1: Make all boxes immortal.
    for each_live_alloc |box, uniq| {
        stats.n_total_boxes += 1;
        if uniq {
            stats.n_unique_boxes += 1;
        } else {
            (*box).header.ref_count = managed::raw::RC_IMMORTAL;
        }
    }

    // Pass 2: Drop all boxes.
    for each_live_alloc |box, uniq| {
        if !uniq {
            let tydesc: *TypeDesc = transmute(copy (*box).header.type_desc);
            let drop_glue: DropGlue = transmute(((*tydesc).drop_glue, 0));
            drop_glue(to_unsafe_ptr(&tydesc), transmute(&(*box).data));
        }
    }

    // Pass 3: Free all boxes.
    for each_live_alloc |box, uniq| {
        if !uniq {
            stats.n_bytes_freed +=
                (*((*box).header.type_desc)).size
                + sys::size_of::<BoxRepr>();
            local_free(transmute(box));
        }
    }

    if debug_mem() {
        // We do logging here w/o allocation.
        let dbg = libc::STDERR_FILENO as io::fd_t;
        dbg.write_str("annihilator stats:");
        dbg.write_str("\n  total_boxes: ");
        dbg.write_uint(stats.n_total_boxes);
        dbg.write_str("\n  unique_boxes: ");
        dbg.write_uint(stats.n_unique_boxes);
        dbg.write_str("\n  bytes_freed: ");
        dbg.write_uint(stats.n_bytes_freed);
        dbg.write_str("\n");
    }
}

/// Bindings to the runtime
pub mod rustrt {
    use libc::c_void;

    #[link_name = "rustrt"]
    pub extern {
        #[rust_stack]
        // FIXME (#4386): Unable to make following method private.
        pub unsafe fn rust_get_task() -> *c_void;
    }
}

<commit_msg>auto merge of #6227 : graydon/rust/issue-6112-box-annihilator, r=graydon<commit_after>// Copyright 2012 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.

#[doc(hidden)];

use libc::{c_char, c_void, intptr_t, uintptr_t};
use ptr::mut_null;
use repr::BoxRepr;
use sys::TypeDesc;
use cast::transmute;

#[cfg(notest)] use ptr::to_unsafe_ptr;

/**
 * Runtime structures
 *
 * NB: These must match the representation in the C++ runtime.
 */

type DropGlue<'self> = &'self fn(**TypeDesc, *c_void);
type FreeGlue<'self> = &'self fn(**TypeDesc, *c_void);

type TaskID = uintptr_t;

struct StackSegment { priv opaque: () }
struct Scheduler { priv opaque: () }
struct SchedulerLoop { priv opaque: () }
struct Kernel { priv opaque: () }
struct Env { priv opaque: () }
struct AllocHeader { priv opaque: () }
struct MemoryRegion { priv opaque: () }

#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
struct Registers {
    data: [u32, ..16]
}

#[cfg(target_arch="mips")]
struct Registers {
    data: [u32, ..32]
}

#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
#[cfg(target_arch="mips")]
struct Context {
    regs: Registers,
    next: *Context,
    pad: [u32, ..3]
}

#[cfg(target_arch="x86_64")]
struct Registers {
    data: [u64, ..22]
}

#[cfg(target_arch="x86_64")]
struct Context {
    regs: Registers,
    next: *Context,
    pad: uintptr_t
}

struct BoxedRegion {
    env: *Env,
    backing_region: *MemoryRegion,
    live_allocs: *BoxRepr
}

#[cfg(target_arch="x86")]
#[cfg(target_arch="arm")]
#[cfg(target_arch="mips")]
struct Task {
    // Public fields
    refcount: intptr_t,                 // 0
    id: TaskID,                         // 4
    pad: [u32, ..2],                    // 8
    ctx: Context,                       // 16
    stack_segment: *StackSegment,       // 96
    runtime_sp: uintptr_t,              // 100
    scheduler: *Scheduler,              // 104
    scheduler_loop: *SchedulerLoop,     // 108

    // Fields known only to the runtime
    kernel: *Kernel,                    // 112
    name: *c_char,                      // 116
    list_index: i32,                    // 120
    boxed_region: BoxedRegion           // 128
}

#[cfg(target_arch="x86_64")]
struct Task {
    // Public fields
    refcount: intptr_t,
    id: TaskID,
    ctx: Context,
    stack_segment: *StackSegment,
    runtime_sp: uintptr_t,
    scheduler: *Scheduler,
    scheduler_loop: *SchedulerLoop,

    // Fields known only to the runtime
    kernel: *Kernel,
    name: *c_char,
    list_index: i32,
    boxed_region: BoxedRegion
}

/*
 * Box annihilation
 *
 * This runs at task death to free all boxes.
 */

struct AnnihilateStats {
    n_total_boxes: uint,
    n_unique_boxes: uint,
    n_bytes_freed: uint
}

unsafe fn each_live_alloc(read_next_before: bool,
                          f: &fn(box: *mut BoxRepr, uniq: bool) -> bool) {
    //! Walks the internal list of allocations

    use managed;

    let task: *Task = transmute(rustrt::rust_get_task());
    let box = (*task).boxed_region.live_allocs;
    let mut box: *mut BoxRepr = transmute(copy box);
    while box != mut_null() {
        let next_before = transmute(copy (*box).header.next);
        let uniq =
            (*box).header.ref_count == managed::raw::RC_MANAGED_UNIQUE;

        if ! f(box, uniq) {
            break
        }

        if read_next_before {
            box = next_before;
        } else {
            box = transmute(copy (*box).header.next);
        }
    }
}

#[cfg(unix)]
fn debug_mem() -> bool {
    ::rt::env::get().debug_mem
}

#[cfg(windows)]
fn debug_mem() -> bool {
    false
}

/// Destroys all managed memory (i.e. @ boxes) held by the current task.
#[cfg(notest)]
#[lang="annihilate"]
pub unsafe fn annihilate() {
    use unstable::lang::local_free;
    use io::WriterUtil;
    use io;
    use libc;
    use sys;
    use managed;

    let mut stats = AnnihilateStats {
        n_total_boxes: 0,
        n_unique_boxes: 0,
        n_bytes_freed: 0
    };

    // Pass 1: Make all boxes immortal.
    //
    // In this pass, nothing gets freed, so it does not matter whether
    // we read the next field before or after the callback.
    for each_live_alloc(true) |box, uniq| {
        stats.n_total_boxes += 1;
        if uniq {
            stats.n_unique_boxes += 1;
        } else {
            (*box).header.ref_count = managed::raw::RC_IMMORTAL;
        }
    }

    // Pass 2: Drop all boxes.
    //
    // In this pass, unique-managed boxes may get freed, but not
    // managed boxes, so we must read the `next` field *after* the
    // callback, as the original value may have been freed.
    for each_live_alloc(false) |box, uniq| {
        if !uniq {
            let tydesc: *TypeDesc = transmute(copy (*box).header.type_desc);
            let drop_glue: DropGlue = transmute(((*tydesc).drop_glue, 0));
            drop_glue(to_unsafe_ptr(&tydesc), transmute(&(*box).data));
        }
    }

    // Pass 3: Free all boxes.
    //
    // In this pass, managed boxes may get freed (but not
    // unique-managed boxes, though I think that none of those are
    // left), so we must read the `next` field before, since it will
    // not be valid after.
    for each_live_alloc(true) |box, uniq| {
        if !uniq {
            stats.n_bytes_freed +=
                (*((*box).header.type_desc)).size
                + sys::size_of::<BoxRepr>();
            local_free(transmute(box));
        }
    }

    if debug_mem() {
        // We do logging here w/o allocation.
        let dbg = libc::STDERR_FILENO as io::fd_t;
        dbg.write_str("annihilator stats:");
        dbg.write_str("\n  total_boxes: ");
        dbg.write_uint(stats.n_total_boxes);
        dbg.write_str("\n  unique_boxes: ");
        dbg.write_uint(stats.n_unique_boxes);
        dbg.write_str("\n  bytes_freed: ");
        dbg.write_uint(stats.n_bytes_freed);
        dbg.write_str("\n");
    }
}

/// Bindings to the runtime
pub mod rustrt {
    use libc::c_void;

    #[link_name = "rustrt"]
    pub extern {
        #[rust_stack]
        // FIXME (#4386): Unable to make following method private.
        pub unsafe fn rust_get_task() -> *c_void;
    }
}

<|endoftext|>


<commit_before>// Copyright 2017 Alexander Reece
//
// 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 std::collections::{btree_map, BTreeMap};

use common::Field;

#[derive(Debug)]
pub struct Fields<'a> {
    fields: BTreeMap<&'a str, Field>,
    has_lifetimes: bool,
}

pub struct Iter<'a>(btree_map::Values<'a, &'a str, Field>);

impl<'a> Fields<'a> {
    pub fn new<'b, I>(iter: I) -> Self
        where I: IntoIterator<Item = &'b Field>
    {
        let mut fields = Fields {
            fields: BTreeMap::new(),
            has_lifetimes: false,
        };
        fields.extend(iter);
        fields
    }

    pub fn extend<'b, I>(&mut self, fields: I)
        where I: IntoIterator<Item = &'b Field>,
    {
        for field in fields {
            let ty = field.ty();

            match self.fields.get(field.name()) {
                Some(ref field) if field.ty() == ty => continue,
                Some(ref field) => panic!(
                    "Conflicting field types for {} ({:?} and {:?})",
                    field.name(), ty, field.ty()
                ),
                None => (),
            }

            if !field.ty().is_copy() {
                self.has_lifetimes = true;
            }

            self.fields.insert(field.name(), field.clone());
        }
    }

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

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

    pub fn iter(&self) -> Iter {
        Iter(self.fields.values())
    }
}

impl<'a> IntoIterator for &'a Fields<'a> {
    type Item = &'a Field;
    type IntoIter = Iter<'a>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a> Iterator for Iter<'a> {
    type Item = &'a Field;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}<commit_msg>[codegen] Update `Fields` to filter reserved fields<commit_after>// Copyright 2017 Alexander Reece
//
// 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 std::collections::{btree_map, BTreeMap};

use common::Field;

#[derive(Debug)]
pub struct Fields<'a> {
    fields: BTreeMap<&'a str, Field>,
    has_lifetimes: bool,
}

pub struct Iter<'a>(btree_map::Values<'a, &'a str, Field>);

impl<'a> Fields<'a> {
    pub fn new<'b, I>(iter: I) -> Self
        where I: IntoIterator<Item = &'b Field>
    {
        let mut fields = Fields {
            fields: BTreeMap::new(),
            has_lifetimes: false,
        };
        fields.extend(iter);
        fields
    }

    pub fn extend<'b, I>(&mut self, fields: I)
        where I: IntoIterator<Item = &'b Field>,
    {
        for field in fields {
            if field.is_reserved() {
                continue;
            }

            let ty = field.ty();

            match self.fields.get(field.name()) {
                Some(ref field) if field.ty() == ty => continue,
                Some(ref field) => panic!(
                    "Conflicting field types for {} ({:?} and {:?})",
                    field.name(), ty, field.ty()
                ),
                None => (),
            }

            if !field.ty().is_copy() {
                self.has_lifetimes = true;
            }

            self.fields.insert(field.name(), field.clone());
        }
    }

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

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

    pub fn iter(&self) -> Iter {
        Iter(self.fields.values())
    }
}

impl<'a> IntoIterator for &'a Fields<'a> {
    type Item = &'a Field;
    type IntoIter = Iter<'a>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a> Iterator for Iter<'a> {
    type Item = &'a Field;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}<|endoftext|>


<commit_before>// Copyright 2016-17 Alexander Reece
//
// 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.

mod class_mod;
mod class_enum;
mod method_mod;
mod root_mod;
mod protocol_trait;
mod spec_mod;
mod spec_struct;

use std::{fs, io};
use std::path::PathBuf;

use {Source, WriteRust};
use format_files;
use common::{Specs, Spec, Class};

use specs;

use self::class_mod::ClassModuleWriter;
use self::method_mod::{MethodsModuleWriter, MethodModuleWriter};
use self::root_mod::RootModuleWriter;
use self::spec_mod::SpecModuleWriter;

pub struct ModulesWriter<'a, S>
    where S: Source + 'a
{
    specs: Specs<'a>,
    source: &'a S,
}

impl<'a, S> ModulesWriter<'a, S>
    where S: Source + 'a
{
    pub fn new(source: &'a S, specs: &'a [&'static specs::Spec]) -> Self {
        let specs = Specs::new(specs.iter().map(|spec| Spec::new(spec)).collect::<Vec<_>>());
        ModulesWriter {
            specs: specs,
            source: source,
        }
    }

    fn write_root_mod(&self) -> io::Result<PathBuf> {
        debug!("Preparing primalgen root module");
        let path = self.source.base_dir().join("mod.rs");
        let writer = RootModuleWriter::new(&self.specs);

        info!("Writing primalgen root module to {}", path.display());
        try!(writer.write_rust_to_path(self.source, &path));
        Ok(path)
    }

    fn write_method_mod(&self) -> io::Result<PathBuf> {
        debug!("Preparing primalgen method module");
        let path = self.source.base_dir().join("method/mod.rs");
        let writer = MethodsModuleWriter::new(&self.specs);
        let _ = fs::remove_file(self.source.base_dir().join("method.rs"));

        info!("Writing primalgen methods module to {}", path.display());
        try!(writer.write_rust_to_path(self.source, &path));
        Ok(path)
    }

    fn write_method_class_mod(&self, class_name: &'a str) -> io::Result<PathBuf> {
        debug!("Preparing primalgen methods class {} module", class_name);
        let path = self.source.base_dir().join(format!("method/{}.rs", class_name));
        let writer = MethodModuleWriter::new(&self.specs, class_name);

        info!("Writing primalgen method class ({}) to {}", class_name, &path.display());
        try!(writer.write_rust_to_path(self.source, &path));
        Ok(path)
    }

    fn write_spec_mod(&self, spec: &Spec) -> io::Result<PathBuf> {
        debug!("Preparing primalgen spec module {}", spec.name());
        let mod_path = self.source.base_dir().join(spec.mod_name());
        let path = mod_path.join("mod.rs");

        let old_path = self.source.base_dir().join(format!("{}.rs", spec.mod_name()));
        println!("Removing potentially old path: {}", old_path.display());
        let _ = fs::remove_file(old_path);

        info!("Writing primalgen spec module {} to {}", spec.name(), path.display());
        let writer = SpecModuleWriter::new(spec);
        try!(writer.write_rust_to_path(self.source, &path));
        Ok(path)
    }

    fn write_class_mod(&self, spec: &Spec, class: &Class) -> io::Result<PathBuf> {
        debug!("Preparing primalgen class module {}", spec.name());
        let mod_path = self.source.base_dir().join(spec.mod_name());
        let path = mod_path.join(format!("{}.rs", class.snake_case()));

        info!("Writing primalgen class module {} to {}", spec.name(), path.display());
        let writer = ClassModuleWriter::new(&self.specs, spec, class);
        try!(writer.write_rust_to_path(self.source, &path));
        Ok(path)
    }

    pub fn write_files(&self) -> io::Result<()> {
        let paths = {
            let num_classes = self.specs.iter().flat_map(|spec| spec.classes()).count();
            let mut paths = Vec::with_capacity(2 + num_classes);

            paths.push(try!(self.write_root_mod()));
            paths.push(try!(self.write_method_mod()));
            for class_name in self.specs.class_names() {
                paths.push(try!(self.write_method_class_mod(class_name)));
            }

            for spec in &self.specs {
                paths.push(try!(self.write_spec_mod(spec)));
                for class in spec.classes() {
                    paths.push(try!(self.write_class_mod(spec, class)));
                }
            }
            paths
        };

        if self.source.should_format() {
            debug!("Formatting files");
            format_files(paths);
        }

        Ok(())
    }
}<commit_msg>[primalgen] Rename ModulesWriter::write_class_mod() to write_spec_class_mod()<commit_after>// Copyright 2016-17 Alexander Reece
//
// 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.

mod class_enum;
mod method_mod;
mod root_mod;
mod protocol_trait;
mod spec_mod;
mod spec_struct;

use std::{fs, io};
use std::path::PathBuf;

use {Source, WriteRust};
use format_files;
use common::{Specs, Spec, Class};

use specs;

use self::method_mod::{MethodsModuleWriter, MethodModuleWriter};
use self::root_mod::RootModuleWriter;
use self::spec_mod::{SpecModuleWriter, SpecClassModuleWriter};

pub struct ModulesWriter<'a, S>
    where S: Source + 'a
{
    specs: Specs<'a>,
    source: &'a S,
}

impl<'a, S> ModulesWriter<'a, S>
    where S: Source + 'a
{
    pub fn new(source: &'a S, specs: &'a [&'static specs::Spec]) -> Self {
        let specs = Specs::new(specs.iter().map(|spec| Spec::new(spec)).collect::<Vec<_>>());
        ModulesWriter {
            specs: specs,
            source: source,
        }
    }

    fn write_root_mod(&self) -> io::Result<PathBuf> {
        debug!("Preparing primalgen root module");
        let path = self.source.base_dir().join("mod.rs");
        let writer = RootModuleWriter::new(&self.specs);

        info!("Writing primalgen root module to {}", path.display());
        try!(writer.write_rust_to_path(self.source, &path));
        Ok(path)
    }

    fn write_method_mod(&self) -> io::Result<PathBuf> {
        debug!("Preparing primalgen method module");
        let path = self.source.base_dir().join("method/mod.rs");
        let writer = MethodsModuleWriter::new(&self.specs);
        let _ = fs::remove_file(self.source.base_dir().join("method.rs"));

        info!("Writing primalgen methods module to {}", path.display());
        try!(writer.write_rust_to_path(self.source, &path));
        Ok(path)
    }

    fn write_method_class_mod(&self, class_name: &'a str) -> io::Result<PathBuf> {
        debug!("Preparing primalgen methods class {} module", class_name);
        let path = self.source.base_dir().join(format!("method/{}.rs", class_name));
        let writer = MethodModuleWriter::new(&self.specs, class_name);

        info!("Writing primalgen method class ({}) to {}", class_name, &path.display());
        try!(writer.write_rust_to_path(self.source, &path));
        Ok(path)
    }

    fn write_spec_mod(&self, spec: &Spec) -> io::Result<PathBuf> {
        debug!("Preparing primalgen spec module {}", spec.name());
        let mod_path = self.source.base_dir().join(spec.mod_name());
        let path = mod_path.join("mod.rs");

        let old_path = self.source.base_dir().join(format!("{}.rs", spec.mod_name()));
        println!("Removing potentially old path: {}", old_path.display());
        let _ = fs::remove_file(old_path);

        info!("Writing primalgen spec module {} to {}", spec.name(), path.display());
        let writer = SpecModuleWriter::new(spec);
        try!(writer.write_rust_to_path(self.source, &path));
        Ok(path)
    }

    fn write_spec_class_mod(&self, spec: &Spec, class: &Class) -> io::Result<PathBuf> {
        debug!("Preparing primalgen class module {}", spec.name());
        let mod_path = self.source.base_dir().join(spec.mod_name());
        let path = mod_path.join(format!("{}.rs", class.snake_case()));

        info!("Writing primalgen class module {} to {}", spec.name(), path.display());
        let writer = SpecClassModuleWriter::new(&self.specs, spec, class);
        try!(writer.write_rust_to_path(self.source, &path));
        Ok(path)
    }

    pub fn write_files(&self) -> io::Result<()> {
        let paths = {
            let num_classes = self.specs.iter().flat_map(|spec| spec.classes()).count();
            let mut paths = Vec::with_capacity(2 + num_classes);

            paths.push(try!(self.write_root_mod()));
            paths.push(try!(self.write_method_mod()));
            for class_name in self.specs.class_names() {
                paths.push(try!(self.write_method_class_mod(class_name)));
            }

            for spec in &self.specs {
                paths.push(try!(self.write_spec_mod(spec)));
                for class in spec.classes() {
                    paths.push(try!(self.write_spec_class_mod(spec, class)));
                }
            }
            paths
        };

        if self.source.should_format() {
            debug!("Formatting files");
            format_files(paths);
        }

        Ok(())
    }
}<|endoftext|>


<commit_before>use super::Tokens;

use std::borrow::Cow;

use proc_macro2::{Literal, Span, Term, TokenNode, TokenTree, TokenStream};

fn tt(kind: TokenNode) -> TokenTree {
    TokenTree {
        span: Span::default(),
        kind: kind,
    }
}

/// Types that can be interpolated inside a [`quote!`] invocation.
///
/// [`quote!`]: macro.quote.html
pub trait ToTokens {
    /// Write `self` to the given `Tokens`.
    ///
    /// Example implementation for a struct representing Rust paths like
    /// `std::cmp::PartialEq`:
    ///
    /// ```
    /// extern crate quote;
    /// use quote::{Tokens, ToTokens};
    ///
    /// extern crate proc_macro2;
    /// use proc_macro2::{TokenTree, TokenNode, Spacing, Span};
    ///
    /// pub struct Path {
    ///     pub global: bool,
    ///     pub segments: Vec<PathSegment>,
    /// }
    ///
    /// impl ToTokens for Path {
    ///     fn to_tokens(&self, tokens: &mut Tokens) {
    ///         for (i, segment) in self.segments.iter().enumerate() {
    ///             if i > 0 || self.global {
    ///                 // Double colon `::`
    ///                 tokens.append(TokenTree {
    ///                     span: Span::def_site(),
    ///                     kind: TokenNode::Op(':', Spacing::Joint),
    ///                 });
    ///                 tokens.append(TokenTree {
    ///                     span: Span::def_site(),
    ///                     kind: TokenNode::Op(':', Spacing::Alone),
    ///                 });
    ///             }
    ///             segment.to_tokens(tokens);
    ///         }
    ///     }
    /// }
    /// #
    /// # pub struct PathSegment;
    /// #
    /// # impl ToTokens for PathSegment {
    /// #     fn to_tokens(&self, tokens: &mut Tokens) {
    /// #         unimplemented!()
    /// #     }
    /// # }
    /// #
    /// # fn main() {}
    /// ```
    fn to_tokens(&self, tokens: &mut Tokens);

    /// Convert `self` directly into a `Tokens` object.
    ///
    /// This method is implicitly implemented using `to_tokens`, and acts as a
    /// convenience method for consumers of the `ToTokens` trait.
    fn into_tokens(self) -> Tokens
    where
        Self: Sized,
    {
        let mut tokens = Tokens::new();
        self.to_tokens(&mut tokens);
        tokens
    }
}

impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T {
    fn to_tokens(&self, tokens: &mut Tokens) {
        (**self).to_tokens(tokens);
    }
}

impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        (**self).to_tokens(tokens);
    }
}

impl<T: ?Sized + ToTokens> ToTokens for Box<T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        (**self).to_tokens(tokens);
    }
}

impl<T: ToTokens> ToTokens for Option<T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        if let Some(ref t) = *self {
            t.to_tokens(tokens);
        }
    }
}

impl ToTokens for str {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(tt(TokenNode::Literal(Literal::string(self))));
    }
}

impl ToTokens for String {
    fn to_tokens(&self, tokens: &mut Tokens) {
        self.as_str().to_tokens(tokens);
    }
}

macro_rules! primitive {
    ($($t:ident)*) => ($(
        impl ToTokens for $t {
            fn to_tokens(&self, tokens: &mut Tokens) {
                tokens.append(tt(TokenNode::Literal(Literal::$t(*self))));
            }
        }
    )*)
}

primitive! {
    i8 i16 i32 i64 isize
    u8 u16 u32 u64 usize
    f32 f64
}

impl ToTokens for char {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(tt(TokenNode::Literal(Literal::character(*self))));
    }
}

impl ToTokens for bool {
    fn to_tokens(&self, tokens: &mut Tokens) {
        let word = if *self { "true" } else { "false" };
        tokens.append(tt(TokenNode::Term(Term::intern(word))));
    }
}

impl ToTokens for Term {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(tt(TokenNode::Term(*self)));
    }
}

impl ToTokens for Literal {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(tt(TokenNode::Literal(self.clone())));
    }
}

impl ToTokens for TokenTree {
    fn to_tokens(&self, dst: &mut Tokens) {
        dst.append(self.clone());
    }
}

impl ToTokens for TokenStream {
    fn to_tokens(&self, dst: &mut Tokens) {
        dst.append_all(self.clone().into_iter());
    }
}
<commit_msg>Implement ToTokens for TokenNode<commit_after>use super::Tokens;

use std::borrow::Cow;

use proc_macro2::{Literal, Span, Term, TokenNode, TokenTree, TokenStream};

fn tt(kind: TokenNode) -> TokenTree {
    TokenTree {
        span: Span::default(),
        kind: kind,
    }
}

/// Types that can be interpolated inside a [`quote!`] invocation.
///
/// [`quote!`]: macro.quote.html
pub trait ToTokens {
    /// Write `self` to the given `Tokens`.
    ///
    /// Example implementation for a struct representing Rust paths like
    /// `std::cmp::PartialEq`:
    ///
    /// ```
    /// extern crate quote;
    /// use quote::{Tokens, ToTokens};
    ///
    /// extern crate proc_macro2;
    /// use proc_macro2::{TokenTree, TokenNode, Spacing, Span};
    ///
    /// pub struct Path {
    ///     pub global: bool,
    ///     pub segments: Vec<PathSegment>,
    /// }
    ///
    /// impl ToTokens for Path {
    ///     fn to_tokens(&self, tokens: &mut Tokens) {
    ///         for (i, segment) in self.segments.iter().enumerate() {
    ///             if i > 0 || self.global {
    ///                 // Double colon `::`
    ///                 tokens.append(TokenTree {
    ///                     span: Span::def_site(),
    ///                     kind: TokenNode::Op(':', Spacing::Joint),
    ///                 });
    ///                 tokens.append(TokenTree {
    ///                     span: Span::def_site(),
    ///                     kind: TokenNode::Op(':', Spacing::Alone),
    ///                 });
    ///             }
    ///             segment.to_tokens(tokens);
    ///         }
    ///     }
    /// }
    /// #
    /// # pub struct PathSegment;
    /// #
    /// # impl ToTokens for PathSegment {
    /// #     fn to_tokens(&self, tokens: &mut Tokens) {
    /// #         unimplemented!()
    /// #     }
    /// # }
    /// #
    /// # fn main() {}
    /// ```
    fn to_tokens(&self, tokens: &mut Tokens);

    /// Convert `self` directly into a `Tokens` object.
    ///
    /// This method is implicitly implemented using `to_tokens`, and acts as a
    /// convenience method for consumers of the `ToTokens` trait.
    fn into_tokens(self) -> Tokens
    where
        Self: Sized,
    {
        let mut tokens = Tokens::new();
        self.to_tokens(&mut tokens);
        tokens
    }
}

impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T {
    fn to_tokens(&self, tokens: &mut Tokens) {
        (**self).to_tokens(tokens);
    }
}

impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        (**self).to_tokens(tokens);
    }
}

impl<T: ?Sized + ToTokens> ToTokens for Box<T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        (**self).to_tokens(tokens);
    }
}

impl<T: ToTokens> ToTokens for Option<T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        if let Some(ref t) = *self {
            t.to_tokens(tokens);
        }
    }
}

impl ToTokens for str {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(tt(TokenNode::Literal(Literal::string(self))));
    }
}

impl ToTokens for String {
    fn to_tokens(&self, tokens: &mut Tokens) {
        self.as_str().to_tokens(tokens);
    }
}

macro_rules! primitive {
    ($($t:ident)*) => ($(
        impl ToTokens for $t {
            fn to_tokens(&self, tokens: &mut Tokens) {
                tokens.append(tt(TokenNode::Literal(Literal::$t(*self))));
            }
        }
    )*)
}

primitive! {
    i8 i16 i32 i64 isize
    u8 u16 u32 u64 usize
    f32 f64
}

impl ToTokens for char {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(tt(TokenNode::Literal(Literal::character(*self))));
    }
}

impl ToTokens for bool {
    fn to_tokens(&self, tokens: &mut Tokens) {
        let word = if *self { "true" } else { "false" };
        tokens.append(tt(TokenNode::Term(Term::intern(word))));
    }
}

impl ToTokens for Term {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(tt(TokenNode::Term(*self)));
    }
}

impl ToTokens for Literal {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(tt(TokenNode::Literal(self.clone())));
    }
}

impl ToTokens for TokenNode {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(tt(self.clone()));
    }
}

impl ToTokens for TokenTree {
    fn to_tokens(&self, dst: &mut Tokens) {
        dst.append(self.clone());
    }
}

impl ToTokens for TokenStream {
    fn to_tokens(&self, dst: &mut Tokens) {
        dst.append_all(self.clone().into_iter());
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::{Read, Write};
use std::net;
use std::net::TcpStream;
#[cfg(feature = "ssl")]
use openssl::ssl::{SslStream, SslConnector};

pub  trait  CDRSTransport: Sized+Read+Write+Send+Sync{

    fn try_clone(&self) -> io::Result<Self>;
    fn close(&mut self, close: net::Shutdown) -> io::Result<()>;
}

impl CDRSTransport  for Transport {

    /// In opposite to `TcpStream`'s `try_clone` this method
    /// creates absolutely new connection - it gets an address
    /// of a peer from `Transport` and creates a new encrypted
    /// transport with new TCP stream under hood.
    fn try_clone(&self) -> io::Result<Transport> {
        let addr = try!( self.tcp.peer_addr());

        net::TcpStream::connect(addr)
        .map( | socket | Transport {
        tcp: socket
        })
    }

     fn close(&mut self, close: net::Shutdown) -> io::Result<()> {
            return self.tcp.shutdown(close);
    }

}

#[derive(Debug)]
pub struct Transport {
    tcp: TcpStream
}

impl Transport {
    pub fn new(addr: &str) -> io::Result<Transport> {
        return net::TcpStream::connect(addr)
            .map(|socket| Transport {
                tcp: socket
            });
    }

}

impl Read for Transport {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        return self.tcp.read(buf);
    }
}

impl Write for Transport {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        return self.tcp.write(buf);
    }

    fn flush(&mut self) -> io::Result<()> {
        return self.tcp.flush();
    }
}
/*************************************/
/** TLS**/
/**************************************/
#[cfg(feature = "ssl")]
impl CDRSTransport for TransportTls{

    /// In opposite to `TcpStream`'s `try_clone` this method
    /// creates absolutely new connection - it gets an address
    /// of a peer from `TransportTls` and creates a new encrypted
    /// connection with a new TCP stream under hood.
     fn try_clone(&self) -> io::Result<TransportTls> {
        let addr = try!(self.ssl.get_ref().peer_addr());
        let ip_string = format!("{}", addr.ip());

        let res =  net::TcpStream::connect(addr)
            .map(|socket|
                     self.connector.connect(ip_string.as_str(), socket)
                         .map(|sslsocket| TransportTls {ssl: sslsocket, connector: self.connector.clone()}));

        res.and_then(|res| {
            res.map(|n: TransportTls| n ).map_err(|e| io::Error::new(io::ErrorKind::Other,e))
        })
    }

     fn close(&mut self, _close: net::Shutdown) -> io::Result<()> {
        return self.ssl.shutdown().map_err(|e| io::Error::new(io::ErrorKind::Other,e)).and_then(|_| Ok(()));
    }
}
#[cfg(feature = "ssl")]
pub struct TransportTls {
    ssl: SslStream<TcpStream>,
    connector: SslConnector
}
#[cfg(feature = "ssl")]
impl TransportTls {

    pub fn new(addr: &str, connector: & SslConnector) -> io::Result<TransportTls> {
        let a: Vec<&str> = addr.split(':').collect();
        let res =  net::TcpStream::connect(addr)
            .map(|socket|
                     connector.connect(a[0], socket)
                         .map(|sslsocket|
                                  TransportTls {
                                      ssl: sslsocket,
                                      connector: connector.clone()
                                  }
                         )
            );

        res.and_then(|res| {
            // transform `Ok(Result<TransportTls,HandshakeError<net::TcpStream>>)` into `Ok(Result<TransportTls, io::Error>)`
            res
                // transform n to TransportTls
                .map(|n: TransportTls| n )
                // transform `HandshakeError` into `'io::Error`
                .map_err(|e| io::Error::new(io::ErrorKind::Other,e))

        })
    }

}
#[cfg(feature = "ssl")]
impl Read for TransportTls {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        return self.ssl.read(buf);
    }
}
#[cfg(feature = "ssl")]
impl Write for TransportTls {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        return self.ssl.write(buf);
    }

    fn flush(&mut self) -> io::Result<()> {
        return self.ssl.flush();
    }
}
<commit_msg>added the comments from alex<commit_after>use std::io;
use std::io::{Read, Write};
use std::net;
use std::net::TcpStream;
#[cfg(feature = "ssl")]
use openssl::ssl::{SslStream, SslConnector};

pub  trait  CDRSTransport: Sized+Read+Write+Send+Sync{

    fn try_clone(&self) -> io::Result<Self>;
    fn close(&mut self, close: net::Shutdown) -> io::Result<()>;
}

#[derive(Debug)]
pub struct Transport {
    tcp: TcpStream
}

impl Transport {
    pub fn new(addr: &str) -> io::Result<Transport> {
        TcpStream::connect(addr).map(|socket| Transport {tcp: socket})
    }

}

impl Read for Transport {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        return self.tcp.read(buf);
    }
}

impl Write for Transport {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        return self.tcp.write(buf);
    }

    fn flush(&mut self) -> io::Result<()> {
        return self.tcp.flush();
    }
}

impl CDRSTransport  for Transport {

    /// In opposite to `TcpStream`'s `try_clone` this method
    /// creates absolutely new connection - it gets an address
    /// of a peer from `Transport` and creates a new encrypted
    /// transport with new TCP stream under hood.
    fn try_clone(&self) -> io::Result<Transport> {
        let addr = try!( self.tcp.peer_addr());
        TcpStream::connect(addr).map( | socket | Transport {tcp: socket})
    }

    fn close(&mut self, close: net::Shutdown) -> io::Result<()> {
        return self.tcp.shutdown(close);
    }

}

/*************************************/
/** TLS**/
/**************************************/

#[cfg(feature = "ssl")]
pub struct TransportTls {
    ssl: SslStream<TcpStream>,
    connector: SslConnector
}
#[cfg(feature = "ssl")]
impl TransportTls {

    pub fn new(addr: &str, connector: & SslConnector) -> io::Result<TransportTls> {
        let a: Vec<&str> = addr.split(':').collect();
        let res =  net::TcpStream::connect(addr)
            .map(|socket|
                     connector.connect(a[0], socket)
                         .map(|sslsocket|
                                  TransportTls {
                                      ssl: sslsocket,
                                      connector: connector.clone()
                                  }
                         )
            );

        res.and_then(|res| {
            // transform `Ok(Result<TransportTls,HandshakeError<net::TcpStream>>)` into `Ok(Result<TransportTls, io::Error>)`
            res
                // transform n to TransportTls
                .map(|n: TransportTls| n )
                // transform `HandshakeError` into `'io::Error`
                .map_err(|e| io::Error::new(io::ErrorKind::Other,e))

        })
    }

}
#[cfg(feature = "ssl")]
impl Read for TransportTls {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        return self.ssl.read(buf);
    }
}
#[cfg(feature = "ssl")]
impl Write for TransportTls {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        return self.ssl.write(buf);
    }

    fn flush(&mut self) -> io::Result<()> {
        return self.ssl.flush();
    }
}

#[cfg(feature = "ssl")]
impl CDRSTransport for TransportTls{

    /// In opposite to `TcpStream`'s `try_clone` this method
    /// creates absolutely new connection - it gets an address
    /// of a peer from `TransportTls` and creates a new encrypted
    /// connection with a new TCP stream under hood.
    fn try_clone(&self) -> io::Result<TransportTls> {
        let addr = try!(self.ssl.get_ref().peer_addr());
        let ip_string = format!("{}", addr.ip());

        let res =  net::TcpStream::connect(addr)
            .map(|socket|
                     self.connector.connect(ip_string.as_str(), socket)
                         .map(|sslsocket| TransportTls {ssl: sslsocket, connector: self.connector.clone()}));

        res.and_then(|res| {
            res.map(|n: TransportTls| n ).map_err(|e| io::Error::new(io::ErrorKind::Other,e))
        })
    }

    fn close(&mut self, _close: net::Shutdown) -> io::Result<()> {
        return self.ssl.shutdown().map_err(|e| io::Error::new(io::ErrorKind::Other,e)).and_then(|_| Ok(()));
    }
}

<|endoftext|>