<commit_before>/// Internal namespace.
pub( crate ) mod private
{
  use crate::prelude::*;

  macro_rules! NODE_ID
  {
    () => { < < Self as GraphNodesNominalInterface >::NodeHandle as HasId >::Id };
  }

  macro_rules! EDGE_ID
  {
    () => { < < Self as GraphEdgesNominalInterface >::EdgeHandle as HasId >::Id };
  }

  ///
  /// Graph which know how to iterate neighbourhood of a node and capable to convert id of a node into a node.
  ///

  pub trait GraphNodesNominalInterface
  {

    /// Handle of a node - entity representing a node or the node itself.
    /// It's not always possible to operate a node directly, for example it it has to be wrapped by cell ref. For that use NodeHandle.
    /// Otherwise NodeHandle could be &Node.
    type NodeHandle : NodeBasicInterface;

    /// Convert argument into node id.
    #[ allow( non_snake_case ) ]
    #[ inline ]
    fn NodeId< Id >( id : Id ) -> NODE_ID!()
    where
      Id : Into< NODE_ID!() >
    {
      id.into()
    }

    /// Convert argument into node id.
    #[ inline ]
    fn node_id< Id >( &self, id : Id ) -> NODE_ID!()
    where
      Id : Into< NODE_ID!() >
    {
      id.into()
    }

    /// Get node with id.
    fn node< Id >( &self, id : Id ) -> &Self::NodeHandle
    where
      Id : Into< NODE_ID!() >
    ;

    // type OutNodesIteratorItem;
    // // type OutNodesIterator : Iterator< Item = ( &'it < Graph::NodeHandle as HasId >::Id, &'it Graph::NodeHandle ) >;
    // type OutNodesIterator : Iterator< Item = Self::OutNodesIteratorItem >;
    // /// Iterate over all nodes.
    // fn out_nodes_ids< Id >( &self, node_id : Id ) -> Self::OutNodesIterator
    // where
    //   Id : Into< NODE_ID!() >
    // ;

    /// Iterate over neighbourhood of the node. Callback gets ids of nodes in neighbourhood of a picked node.
    fn out_nodes_ids< 'a, 'b, Id >( &'a self, node_id : Id )
    ->
    Box< dyn Iterator< Item = NODE_ID!() > + 'b >
    where
      Id : Into< NODE_ID!() >,
      'a : 'b,
    ;

    /// Iterate over neighbourhood of the node. Callback gets ids and reference on itself of nodes in neighbourhood of a picked node.
    fn out_nodes< 'a, 'b, Id >( &'a self, node_id : Id )
    ->
    Box< dyn Iterator< Item = ( NODE_ID!(), &< Self as GraphNodesNominalInterface >::NodeHandle ) > + 'b >
    where
      Id : Into< NODE_ID!() >,
      'a : 'b,
    {
      Box::new( self.out_nodes_ids( node_id ).map( | id |
      {
        ( id, self.node( id ) )
      }))
    }

  }

  ///
  /// Graph which know how to iterate neighbourhood of a node and capable to convert id of a node into a node.
  ///

  pub trait GraphEdgesNominalInterface
  where
    Self : GraphNodesNominalInterface,
  {

    /// Handle of an edge - entity representing an edge or the edge itself.
    /// It's not always possible to operate an edge directly, for example it it has to be wrapped by cell ref. For that use NodeHandle.
    /// Otherwise EdgeHandle could be &Node.
    type EdgeHandle : EdgeBasicInterface;

    /// Convert argument into edge id.
    #[ allow( non_snake_case ) ]
    #[ inline ]
    fn EdgeId< Id >( id : Id ) -> EDGE_ID!()
    where
      Id : Into< EDGE_ID!() >
    {
      id.into()
    }

    /// Convert argument into edge id.
    #[ inline ]
    fn edge_id< Id >( &self, id : Id ) -> EDGE_ID!()
    where
      Id : Into< EDGE_ID!() >
    {
      Self::EdgeId( id )
    }

// xxx
//     /// Convert argument into edges ids.
//     #[ allow( non_snake_case ) ]
//     #[ inline ]
//     fn EdgesIds< In, Out >( src : In< EDGE_ID!() > ) -> Out< EDGE_ID!() >
//     where
//       In : IdsFromCollection,
//       Out : IdsCollection,
//     {
//       src.into()
//     }
//
//     /// Get edges with ids.
//     #[ inline ]
//     fn edges_ids< In, Out >( &self, src : In< EDGE_ID!() > ) -> Out< EDGE_ID!() >
//     where
//       In : IdsFromCollection,
//       Out : IdsCollection,
//     {
//       Self::EdgesIds( src )
//     }

    /// Get edge with id.
    fn edge< Id >( &self, id : Id ) -> &Self::EdgeHandle
    where
      Id : Into< EDGE_ID!() >
    ;

    /// Iterate over output edges of the node. Callback gets ids of nodes in neighbourhood of a picked node.
    fn out_edges_ids< 'a, 'b, IntoId >( &'a self, node_id : IntoId )
    ->
    Box< dyn Iterator< Item = EDGE_ID!() > + 'b >
    where
      IntoId : Into< NODE_ID!() >,
      'a : 'b,
    ;

    /// Iterate over output edges of the node. Callback gets ids and references of edges in neighbourhood of a picked node.
    fn out_edges< 'a, 'b, IntoId >( &'a self, node_id : IntoId )
    ->
    Box< dyn Iterator< Item = ( EDGE_ID!(), &< Self as GraphEdgesNominalInterface >::EdgeHandle ) > + 'b >
    where
      IntoId : Into< NODE_ID!() >,
      'a : 'b,
    {
      Box::new( self.out_edges_ids( node_id ).map( | id |
      {
        ( id, self.edge( id ) )
      }))
    }

  }

  /// Into iterator of nodes.

  pub trait IntoIteratorOfNodes
  {
    type NodesIteratorItem;
    type NodesIterator : Iterator< Item = Self::NodesIteratorItem >;
    // /// Iterate over all nodes.
    // fn nodes( self ) -> Self::NodesIterator;
  }

  //

  impl< 'it, Graph > IntoIteratorOfNodes
  for &'it Graph
  where
    Graph : GraphNodesNominalInterface,
  {
    type NodesIteratorItem = ( &'it < Graph::NodeHandle as HasId >::Id, &'it Graph::NodeHandle );
    type NodesIterator = std::collections::hash_map::Iter< 'it, < Graph::NodeHandle as HasId >::Id, Graph::NodeHandle >;
    // fn nodes( self ) -> Self::NodesIterator
    // {
    //   self.map.iter()
    // }
  }

  ///
  /// Graph nodes of which is possible to enumerate.
  ///

  // pub trait GraphNodesEnumerableInterface< 'it, 'it2, It >
  pub trait GraphNodesEnumerableInterface
  where
    Self : GraphNodesNominalInterface,
    // It : Iterator< Item = &'it2 ( NODE_ID!(), &'it < Self as GraphNodesNominalInterface >::NodeHandle ) >,
    // < Self as GraphNodesNominalInterface >::NodeHandle : 'it,
    // 'it : 'it2,
  {

    // type NodesIteratorItem;
    // // type NodesIterator : Iterator< Item = ( &'it < Graph::NodeHandle as HasId >::Id, &'it Graph::NodeHandle ) >;
    // type NodesIterator : Iterator< Item = Self::NodesIteratorItem >;
    // /// Iterate over all nodes.
    // fn nodes( self ) -> Self::NodesIterator;

    /// Iterate over all nodes.
    fn nodes< 'a, 'b >( &'a self )
    ->
    Box< dyn Iterator< Item = ( NODE_ID!(), &< Self as GraphNodesNominalInterface >::NodeHandle ) > + 'b >
    where
      'a : 'b,
    ;

    /// Number of nodes. Order of the graph.
    fn nnodes( &self ) -> usize
    {
      self.nodes().count()
    }

  }

  ///
  /// Graph edges of which is possible to enumerate.
  ///

  pub trait GraphEdgesEnumerableInterface
  where
    Self :
      GraphNodesNominalInterface +
      GraphEdgesNominalInterface +
    ,
  {

    /// Iterate over all edges.
    fn edges< 'a, 'b >( &'a self )
    ->
    Box< dyn Iterator< Item = ( EDGE_ID!(), &< Self as GraphEdgesNominalInterface >::EdgeHandle ) > + 'b >
    where
      'a : 'b,
    ;

    /// Number of edges. Size of the graph.
    fn nedges( &self ) -> usize
    {
      self.edges().count()
    }

  }

  ///
  /// Graph interface which allow to add more nodes. Know nothing about edges.
  ///

  pub trait GraphNodesExtendableInterface
  where
    Self :
      GraphNodesNominalInterface +
    ,
  {

    /// Get node with id mutably.
    fn node_mut< Id >( &mut self, id : Id ) -> &mut Self::NodeHandle
    where
      Id : Into< NODE_ID!() >
    ;

    /// Add out nodes to the node.
    fn node_add_out_nodes< IntoId1, IntoId2, Iter >
    (
      &mut self,
      node_id : IntoId1,
      out_nodes_iter : Iter,
    )
    where
      IntoId1 : Into< NODE_ID!() >,
      IntoId2 : Into< NODE_ID!() >,
      Iter : IntoIterator< Item = IntoId2 >,
      Iter::IntoIter : Clone,
    ;

    /// Add out edges to the node.
    fn node_add_out_node< IntoId1, IntoId2 >
    (
      &mut self,
      node_id : IntoId1,
      out_node_id : IntoId2,
    )
    where
      IntoId1 : Into< NODE_ID!() >,
      IntoId1 : Clone,
      IntoId2 : Into< NODE_ID!() >,
      IntoId2 : Clone,
    {
      self.node_add_out_nodes( node_id, core::iter::once( out_node_id ) );
    }

    /// Either make new or get existing node.
    fn node_making< Id >( &mut self, id : Id ) -> NODE_ID!()
    where
      Id : Into< NODE_ID!() >
    ;

    /// Make edges.
    fn make_with_edge_list< IntoIter, Id >( &mut self, into_iter : IntoIter )
    where
      Id : Into< NODE_ID!() >,
      IntoIter : IntoIterator< Item = Id >,
      IntoIter::IntoIter : core::iter::ExactSizeIterator< Item = Id >,
    {
      use wtools::iter::prelude::*;
      let iter = into_iter.into_iter();
      debug_assert_eq!( iter.len() % 2, 0 );
      for mut chunk in &iter.chunks( 2 )
      {
        let id1 = chunk.next().unwrap().into();
        let id2 = chunk.next().unwrap().into();
        self.node_making( id1 );
        self.node_making( id2 );
        self.node_add_out_node( id1, id2 );
      }

    }

  }

  ///
  /// Graph interface which allow to add more edges.
  ///

  pub trait GraphEdgesExtendableInterface
  where
    Self :
      GraphNodesNominalInterface +
      GraphEdgesNominalInterface +
      GraphNodesExtendableInterface +
    ,
  {

    /// Either make new or get existing edge for specified nodes.
    fn _edge_id_generate( &mut self, node1 : NODE_ID!(), node2 : NODE_ID!() ) -> EDGE_ID!();

    /// Either make new or get existing edge for specified nodes.
    fn _edge_add( &mut self, edge_id : EDGE_ID!(), node1 : NODE_ID!(), node2 : NODE_ID!() );

    /// Either make new or get existing edge for specified nodes.
    fn _edge_make_for_nodes< IntoNodeId1, IntoNodeId2 >( &mut self, node1 : IntoNodeId1, node2 : IntoNodeId2 ) -> EDGE_ID!()
    where
      IntoNodeId1 : Into< NODE_ID!() >,
      IntoNodeId2 : Into< NODE_ID!() >,
    {
      let node1 = node1.into();
      let node2 = node2.into();
      let edge = self._edge_id_generate( node1, node2 );
      self._edge_add( edge, node1, node2 );
      edge
    }

  }

  ///
  /// Graph nodes of which has a kind.
  ///

  pub trait GraphNodesKindGetterInterface
  where
    Self : GraphNodesNominalInterface,
  {
    /// Enumerate kinds of the node.
    type NodeKind : crate::NodeKindInterface;
    /// Get kind of the node.
    fn node_kind( &self, node_id : NODE_ID!() ) -> Self::NodeKind;
  }

  ///
  /// Graph nodes of which has a kind.
  ///

  pub trait GraphEdgesKindGetterInterface
  where
    Self :
      GraphNodesNominalInterface +
      GraphEdgesNominalInterface +
    ,
  {
    /// Enumerate kinds of the node.
    type EdgeKind : crate::EdgeKindInterface;
    /// Get kind of the node.
    fn edge_kind( &self, edge_id : EDGE_ID!() ) -> Self::EdgeKind;
  }

}

/// Protected namespace of the module.
pub mod protected
{
  pub use super::orphan::*;
}

pub use protected::*;

/// Parented namespace of the module.
pub mod orphan
{
  pub use super::exposed::*;
}

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::prelude::*;
}

pub use exposed::*;

/// Prelude to use essentials: `use my_module::prelude::*`.
pub mod prelude
{
  pub use super::private::
  {
    GraphNodesNominalInterface,
    GraphEdgesNominalInterface,
    GraphNodesEnumerableInterface,
    GraphEdgesEnumerableInterface,
    GraphNodesExtendableInterface,
    GraphEdgesExtendableInterface,
    GraphNodesKindGetterInterface,
    GraphEdgesKindGetterInterface,
  };
}
<commit_msg>!test<commit_after>/// Internal namespace.
pub( crate ) mod private
{
  use crate::prelude::*;

  macro_rules! NODE_ID
  {
    () => { < < Self as GraphNodesNominalInterface >::NodeHandle as HasId >::Id };
  }

  macro_rules! EDGE_ID
  {
    () => { < < Self as GraphEdgesNominalInterface >::EdgeHandle as HasId >::Id };
  }

  ///
  /// Graph which know how to iterate neighbourhood of a node and capable to convert id of a node into a node.
  ///

  pub trait GraphNodesNominalInterface
  {

    /// Handle of a node - entity representing a node or the node itself.
    /// It's not always possible to operate a node directly, for example it it has to be wrapped by cell ref. For that use NodeHandle.
    /// Otherwise NodeHandle could be &Node.
    type NodeHandle : NodeBasicInterface;

    /// Convert argument into node id.
    #[ allow( non_snake_case ) ]
    #[ inline ]
    fn NodeId< Id >( id : Id ) -> NODE_ID!()
    where
      Id : Into< NODE_ID!() >
    {
      id.into()
    }

    /// Convert argument into node id.
    #[ inline ]
    fn node_id< Id >( &self, id : Id ) -> NODE_ID!()
    where
      Id : Into< NODE_ID!() >
    {
      id.into()
    }

    /// Get node with id.
    fn node< Id >( &self, id : Id ) -> &Self::NodeHandle
    where
      Id : Into< NODE_ID!() >
    ;

    // type OutNodesIteratorItem;
    // // type OutNodesIterator : Iterator< Item = ( &'it < Graph::NodeHandle as HasId >::Id, &'it Graph::NodeHandle ) >;
    // type OutNodesIterator : Iterator< Item = Self::OutNodesIteratorItem >;
    // /// Iterate over all nodes.
    // fn out_nodes_ids< Id >( &self, node_id : Id ) -> Self::OutNodesIterator
    // where
    //   Id : Into< NODE_ID!() >
    // ;

    /// Iterate over neighbourhood of the node. Callback gets ids of nodes in neighbourhood of a picked node.
    fn out_nodes_ids< 'a, 'b, Id >( &'a self, node_id : Id )
    ->
    Box< dyn Iterator< Item = NODE_ID!() > + 'b >
    where
      Id : Into< NODE_ID!() >,
      'a : 'b,
    ;

    /// Iterate over neighbourhood of the node. Callback gets ids and reference on itself of nodes in neighbourhood of a picked node.
    fn out_nodes< 'a, 'b, Id >( &'a self, node_id : Id )
    ->
    Box< dyn Iterator< Item = ( NODE_ID!(), &< Self as GraphNodesNominalInterface >::NodeHandle ) > + 'b >
    where
      Id : Into< NODE_ID!() >,
      'a : 'b,
    {
      Box::new( self.out_nodes_ids( node_id ).map( | id |
      {
        ( id, self.node( id ) )
      }))
    }

  }

  ///
  /// Graph which know how to iterate neighbourhood of a node and capable to convert id of a node into a node.
  ///

  pub trait GraphEdgesNominalInterface
  where
    Self : GraphNodesNominalInterface,
  {

    /// Handle of an edge - entity representing an edge or the edge itself.
    /// It's not always possible to operate an edge directly, for example it it has to be wrapped by cell ref. For that use NodeHandle.
    /// Otherwise EdgeHandle could be &Node.
    type EdgeHandle : EdgeBasicInterface;

    /// Convert argument into edge id.
    #[ allow( non_snake_case ) ]
    #[ inline ]
    fn EdgeId< Id >( id : Id ) -> EDGE_ID!()
    where
      Id : Into< EDGE_ID!() >
    {
      id.into()
    }

    /// Convert argument into edge id.
    #[ inline ]
    fn edge_id< Id >( &self, id : Id ) -> EDGE_ID!()
    where
      Id : Into< EDGE_ID!() >
    {
      Self::EdgeId( id )
    }

// xxx
//     /// Convert argument into edges ids.
//     #[ allow( non_snake_case ) ]
//     #[ inline ]
//     fn EdgesIds< In, Out >( src : In< EDGE_ID!() > ) -> Out< EDGE_ID!() >
//     where
//       In : IdsFromCollection,
//       Out : IdsCollection,
//     {
//       src.into()
//     }
//
//     /// Get edges with ids.
//     #[ inline ]
//     fn edges_ids< In, Out >( &self, src : In< EDGE_ID!() > ) -> Out< EDGE_ID!() >
//     where
//       In : IdsFromCollection,
//       Out : IdsCollection,
//     {
//       Self::EdgesIds( src )
//     }

    /// Get edge with id.
    fn edge< Id >( &self, id : Id ) -> &Self::EdgeHandle
    where
      Id : Into< EDGE_ID!() >
    ;

    /// Iterate over output edges of the node. Callback gets ids of nodes in neighbourhood of a picked node.
    fn out_edges_ids< 'a, 'b, IntoId >( &'a self, node_id : IntoId )
    ->
    Box< dyn Iterator< Item = EDGE_ID!() > + 'b >
    where
      IntoId : Into< NODE_ID!() >,
      'a : 'b,
    ;

    /// Iterate over output edges of the node. Callback gets ids and references of edges in neighbourhood of a picked node.
    fn out_edges< 'a, 'b, IntoId >( &'a self, node_id : IntoId )
    ->
    Box< dyn Iterator< Item = ( EDGE_ID!(), &< Self as GraphEdgesNominalInterface >::EdgeHandle ) > + 'b >
    where
      IntoId : Into< NODE_ID!() >,
      'a : 'b,
    {
      Box::new( self.out_edges_ids( node_id ).map( | id |
      {
        ( id, self.edge( id ) )
      }))
    }

  }

  /// Into iterator of nodes.

  pub trait IntoIteratorOfNodes
  {
    type NodesIteratorItem;
    type NodesIterator : Iterator< Item = Self::NodesIteratorItem >;
    // /// Iterate over all nodes.
    // fn nodes( self ) -> Self::NodesIterator;
  }

  //

  impl< 'it, Graph > IntoIteratorOfNodes
  for &'it Graph
  where
    Graph : GraphNodesNominalInterface,
  {
    type NodesIteratorItem = ( &'it < Graph::NodeHandle as HasId >::Id, &'it Graph::NodeHandle );
    type NodesIterator = std::collections::hash_map::Iter< 'it, < Graph::NodeHandle as HasId >::Id, Graph::NodeHandle >;
    // fn nodes( self ) -> Self::NodesIterator
    // {
    //   self.map.iter()
    // }
  }

  ///
  /// Graph nodes of which is possible to enumerate.
  ///

  // pub trait GraphNodesEnumerableInterface< 'it, 'it2, It >
  pub trait GraphNodesEnumerableInterface
  where
    Self : GraphNodesNominalInterface,
    // It : Iterator< Item = &'it2 ( NODE_ID!(), &'it < Self as GraphNodesNominalInterface >::NodeHandle ) >,
    // < Self as GraphNodesNominalInterface >::NodeHandle : 'it,
    // 'it : 'it2,
  {

    // type NodesIteratorItem;
    // // type NodesIterator : Iterator< Item = ( &'it < Graph::NodeHandle as HasId >::Id, &'it Graph::NodeHandle ) >;
    // type NodesIterator : Iterator< Item = Self::NodesIteratorItem >;
    // /// Iterate over all nodes.
    // fn nodes( self ) -> Self::NodesIterator;

    /// Iterate over all nodes.
    fn nodes< 'a, 'b >( &'a self )
    ->
    Box< dyn Iterator< Item = ( NODE_ID!(), &< Self as GraphNodesNominalInterface >::NodeHandle ) > + 'b >
    where
      'a : 'b,
    ;

    /// Number of nodes. Order of the graph.
    fn nnodes( &self ) -> usize
    {
      self.nodes().count()
    }

  }

  ///
  /// Graph edges of which is possible to enumerate.
  ///

  pub trait GraphEdgesEnumerableInterface
  where
    Self :
      GraphNodesNominalInterface +
      GraphEdgesNominalInterface +
    ,
  {

    /// Iterate over all edges.
    fn edges< 'a, 'b >( &'a self )
    ->
    Box< dyn Iterator< Item = ( EDGE_ID!(), &< Self as GraphEdgesNominalInterface >::EdgeHandle ) > + 'b >
    where
      'a : 'b,
    ;

    /// Number of edges. Size of the graph.
    fn nedges( &self ) -> usize
    {
      self.edges().count()
    }

  }

  ///
  /// Graph interface which allow to add more nodes. Know nothing about edges.
  ///

  pub trait GraphNodesExtendableInterface
  where
    Self :
      GraphNodesNominalInterface +
    ,
  {

    /// Get node with id mutably.
    fn node_mut< Id >( &mut self, id : Id ) -> &mut Self::NodeHandle
    where
      Id : Into< NODE_ID!() >
    ;

    /// Add out nodes to the node.
    fn node_add_out_nodes< IntoId1, IntoId2, Iter >
    (
      &mut self,
      node_id : IntoId1,
      out_nodes_iter : Iter,
    )
    where
      IntoId1 : Into< NODE_ID!() >,
      IntoId2 : Into< NODE_ID!() >,
      Iter : IntoIterator< Item = IntoId2 >,
      Iter::IntoIter : Clone,
    ;

    /// Add out edges to the node.
    fn node_add_out_node< IntoId1, IntoId2 >
    (
      &mut self,
      node_id : IntoId1,
      out_node_id : IntoId2,
    )
    where
      IntoId1 : Into< NODE_ID!() >,
      IntoId1 : Clone,
      IntoId2 : Into< NODE_ID!() >,
      IntoId2 : Clone,
    {
      self.node_add_out_nodes( node_id, core::iter::once( out_node_id ) );
    }

    /// Either make new or get existing node.
    fn node_making< Id >( &mut self, id : Id ) -> NODE_ID!()
    where
      Id : Into< NODE_ID!() >
    ;

    /// Make edges.
    fn make_with_edge_list< IntoIter, Id >( &mut self, into_iter : IntoIter )
    where
      Id : Into< NODE_ID!() >,
      IntoIter : IntoIterator< Item = Id >,
      IntoIter::IntoIter : core::iter::ExactSizeIterator< Item = Id >,
    {
      use wtools::iter::prelude::*;
      let iter = into_iter.into_iter();
      debug_assert_eq!( iter.len() % 2, 0 );
      for mut chunk in &iter.chunks( 2 )
      {
        let id1 = chunk.next().unwrap().into();
        let id2 = chunk.next().unwrap().into();
        self.node_making( id1 );
        self.node_making( id2 );
        self.node_add_out_node( id1, id2 );
      }

    }

  }

  ///
  /// Graph interface which allow to add more edges.
  ///

  pub trait GraphEdgesExtendableInterface
  where
    Self :
      GraphNodesNominalInterface +
      GraphEdgesNominalInterface +
      GraphNodesExtendableInterface +
    ,
  {

    /// Either make new or get existing edge for specified nodes.
    fn _edge_id_generate( &mut self, node1 : NODE_ID!(), node2 : NODE_ID!() ) -> EDGE_ID!();

    /// Either make new or get existing edge for specified nodes.
    fn _edge_add( &mut self, edge_id : EDGE_ID!(), node1 : NODE_ID!(), node2 : NODE_ID!() );

    /// Either make new or get existing edge for specified nodes.
    fn _edge_make_for_nodes< IntoNodeId1, IntoNodeId2 >( &mut self, node1 : IntoNodeId1, node2 : IntoNodeId2 ) -> EDGE_ID!()
    where
      IntoNodeId1 : Into< NODE_ID!() >,
      IntoNodeId2 : Into< NODE_ID!() >,
    {
      let node1 = node1.into();
      let node2 = node2.into();
      let edge = self._edge_id_generate( node1, node2 );
      self._edge_add( edge, node1, node2 );
      edge
    }

  }

  ///
  /// Graph nodes of which has a kind.
  ///

  pub trait GraphNodesKindGetterInterface
  where
    Self : GraphNodesNominalInterface,
  {
    /// Enumerate kinds of the node.
    type NodeKind : crate::NodeKindInterface;
    /// Get kind of the node.
    fn node_kind( &self, node_id : NODE_ID!() ) -> Self::NodeKind;
  }

  ///
  /// Graph nodes of which has a kind.
  ///

  pub trait GraphEdgesKindGetterInterface
  where
    Self :
      GraphNodesNominalInterface +
      GraphEdgesNominalInterface +
    ,
  {
    /// Enumerate kinds of the node.
    type EdgeKind : crate::EdgeKindInterface;
    /// Get kind of the node.
    fn edge_kind( &self, edge_id : EDGE_ID!() ) -> Self::EdgeKind;
  }

}

/// Protected namespace of the module.
pub mod protected
{
  pub use super::orphan::*;
}

pub use protected::*;

/// Parented namespace of the module.
pub mod orphan
{
  pub use super::exposed::*;
}

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::prelude::*;
}

pub use exposed::*;

/// Prelude to use essentials: `use my_module::prelude::*`.
pub mod prelude
{
  pub use super::private::
  {
    GraphNodesNominalInterface,
    GraphEdgesNominalInterface,
    GraphNodesEnumerableInterface,
    GraphEdgesEnumerableInterface,
    GraphNodesExtendableInterface,
    GraphEdgesExtendableInterface,
    GraphNodesKindGetterInterface,
    GraphEdgesKindGetterInterface,
  };
}
<|endoftext|>


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

use std::env;
use common::Config;

/// Conversion table from triple OS name to Rust SYSNAME
const OS_TABLE: &'static [(&'static str, &'static str)] = &[
    ("android", "android"),
    ("bitrig", "bitrig"),
    ("darwin", "macos"),
    ("dragonfly", "dragonfly"),
    ("freebsd", "freebsd"),
    ("linux", "linux"),
    ("mingw32", "windows"),
    ("openbsd", "openbsd"),
    ("win32", "windows"),
    ("windows", "windows"),
];

const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
    ("aarch64", "aarch64"),
    ("amd64", "x86_64"),
    ("arm", "arm"),
    ("arm64", "aarch64"),
    ("hexagon", "hexagon"),
    ("i386", "x86"),
    ("i686", "x86"),
    ("mips", "mips"),
    ("msp430", "msp430"),
    ("powerpc", "powerpc"),
    ("s390x", "systemz"),
    ("sparc", "sparc"),
    ("x86_64", "x86_64"),
    ("xcore", "xcore"),
];

pub fn get_os(triple: &str) -> &'static str {
    for &(triple_os, os) in OS_TABLE {
        if triple.contains(triple_os) {
            return os
        }
    }
    panic!("Cannot determine OS from triple");
}
pub fn get_arch(triple: &str) -> &'static str {
    for &(triple_arch, arch) in ARCH_TABLE {
        if triple.contains(triple_arch) {
            return arch
        }
    }
    panic!("Cannot determine Architecture from triple");
}

pub fn make_new_path(path: &str) -> String {
    assert!(cfg!(windows));
    // Windows just uses PATH as the library search path, so we have to
    // maintain the current value while adding our own
    match env::var(lib_path_env_var()) {
        Ok(curr) => {
            format!("{}{}{}", path, path_div(), curr)
        }
        Err(..) => path.to_string()
    }
}

pub fn lib_path_env_var() -> &'static str { "PATH" }
fn path_div() -> &'static str { ";" }

pub fn logv(config: &Config, s: String) {
    debug!("{}", s);
    if config.verbose { println!("{}", s); }
}
<commit_msg>Add iOS triple mapping so tests can run<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::env;
use common::Config;

/// Conversion table from triple OS name to Rust SYSNAME
const OS_TABLE: &'static [(&'static str, &'static str)] = &[
    ("android", "android"),
    ("bitrig", "bitrig"),
    ("darwin", "macos"),
    ("dragonfly", "dragonfly"),
    ("freebsd", "freebsd"),
    ("ios", "ios"),
    ("linux", "linux"),
    ("mingw32", "windows"),
    ("openbsd", "openbsd"),
    ("win32", "windows"),
    ("windows", "windows"),
];

const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
    ("aarch64", "aarch64"),
    ("amd64", "x86_64"),
    ("arm", "arm"),
    ("arm64", "aarch64"),
    ("hexagon", "hexagon"),
    ("i386", "x86"),
    ("i686", "x86"),
    ("mips", "mips"),
    ("msp430", "msp430"),
    ("powerpc", "powerpc"),
    ("s390x", "systemz"),
    ("sparc", "sparc"),
    ("x86_64", "x86_64"),
    ("xcore", "xcore"),
];

pub fn get_os(triple: &str) -> &'static str {
    for &(triple_os, os) in OS_TABLE {
        if triple.contains(triple_os) {
            return os
        }
    }
    panic!("Cannot determine OS from triple");
}
pub fn get_arch(triple: &str) -> &'static str {
    for &(triple_arch, arch) in ARCH_TABLE {
        if triple.contains(triple_arch) {
            return arch
        }
    }
    panic!("Cannot determine Architecture from triple");
}

pub fn make_new_path(path: &str) -> String {
    assert!(cfg!(windows));
    // Windows just uses PATH as the library search path, so we have to
    // maintain the current value while adding our own
    match env::var(lib_path_env_var()) {
        Ok(curr) => {
            format!("{}{}{}", path, path_div(), curr)
        }
        Err(..) => path.to_string()
    }
}

pub fn lib_path_env_var() -> &'static str { "PATH" }
fn path_div() -> &'static str { ";" }

pub fn logv(config: &Config, s: String) {
    debug!("{}", s);
    if config.verbose { println!("{}", s); }
}
<|endoftext|>


<commit_before>use serde_json::Value;

/// "Unwrap" JSON nodes so that the node(s) specified by the pointer is the new root(s)
pub fn unwrap(pointer: &str, value: Value) -> Vec<Value> {
    dbg!(pointer);
    let pointer_tokens: Vec<&str> = if pointer.is_empty() || pointer == "/" {
        return vec![value];
    } else {
        if pointer.starts_with('/') {
            pointer.split('/').skip(1).collect()
        } else {
            pointer.split('/').collect()
        }
    };

    if pointer_tokens.is_empty() {
        return vec![value];
    }

    let mut next: Vec<Value> = vec![value];
    for pointer_token in dbg!(pointer_tokens) {
        let mut work = Vec::new();
        std::mem::swap(&mut work, &mut next);
        for val in work {
            match val {
                Value::Object(mut values) => {
                    if let Some(y) = values.remove(pointer_token) {
                        next.push(y);
                    } else if pointer_token == "-" {
                        next.append(&mut values.into_iter().map(|(_k, v)| v).collect())
                    }
                }
                Value::Array(mut values) => {
                    if pointer_token == "-" {
                        next.append(&mut values)
                    } else if let Ok(i) = pointer_token.parse::<usize>() {
                        if i < values.len() {
                            next.push(values.remove(i));
                        }
                    }
                }
                Value::Null => {}
                Value::Bool(_) => {}
                Value::Number(_) => {}
                Value::String(_) => {}
            }
        }
    }

    return next;
}

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

    #[test]
    fn test_unwrap() {
        assert_eq!(unwrap("", json!(true)), vec![json!(true)]);
        assert_eq!(unwrap("/", json!(true)), vec![json!(true)]);
        assert_eq!(unwrap("/foo", json!({ "foo": true })), vec![json!(true)]);
        assert_eq!(
            unwrap(
                "/foo/-/bar",
                json!({
                    "foo": [
                        { "bar": 1 },
                        { "bar": 2 },
                        { "nope": "hello" },
                        { "bar": 3 },
                    ]
                })
            ),
            vec![json!(1), json!(2), json!(3)]
        );
    }
}
<commit_msg>Clean up a couple of forgotten dbg!() calls<commit_after>use serde_json::Value;

/// "Unwrap" JSON nodes so that the node(s) specified by the pointer is the new root(s)
pub fn unwrap(pointer: &str, value: Value) -> Vec<Value> {
    let pointer_tokens: Vec<&str> = if pointer.is_empty() || pointer == "/" {
        return vec![value];
    } else {
        if pointer.starts_with('/') {
            pointer.split('/').skip(1).collect()
        } else {
            pointer.split('/').collect()
        }
    };

    if pointer_tokens.is_empty() {
        return vec![value];
    }

    let mut next: Vec<Value> = vec![value];
    for pointer_token in pointer_tokens {
        let mut work = Vec::new();
        std::mem::swap(&mut work, &mut next);
        for val in work {
            match val {
                Value::Object(mut values) => {
                    if let Some(y) = values.remove(pointer_token) {
                        next.push(y);
                    } else if pointer_token == "-" {
                        next.append(&mut values.into_iter().map(|(_k, v)| v).collect())
                    }
                }
                Value::Array(mut values) => {
                    if pointer_token == "-" {
                        next.append(&mut values)
                    } else if let Ok(i) = pointer_token.parse::<usize>() {
                        if i < values.len() {
                            next.push(values.remove(i));
                        }
                    }
                }
                Value::Null => {}
                Value::Bool(_) => {}
                Value::Number(_) => {}
                Value::String(_) => {}
            }
        }
    }

    return next;
}

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

    #[test]
    fn test_unwrap() {
        assert_eq!(unwrap("", json!(true)), vec![json!(true)]);
        assert_eq!(unwrap("/", json!(true)), vec![json!(true)]);
        assert_eq!(unwrap("/foo", json!({ "foo": true })), vec![json!(true)]);
        assert_eq!(
            unwrap(
                "/foo/-/bar",
                json!({
                    "foo": [
                        { "bar": 1 },
                        { "bar": 2 },
                        { "nope": "hello" },
                        { "bar": 3 },
                    ]
                })
            ),
            vec![json!(1), json!(2), json!(3)]
        );
    }
}
<|endoftext|>


<commit_before>use std::iter::ExactSizeIterator;

use bip_bencode::{BencodeMut, BMutAccess};
use bip_util::sha::{self, ShaHash};

use accessor::{Accessor, IntoAccessor};
use error::ParseResult;
use parse;

mod buffer;
mod worker;

// Piece length is inversly related to the file size.
// Transfer reliability is inversly related to the piece length.
// Transfer reliability is directly related to the file size.

// These statements hold even today, although the piece lengths that were historically
// recommended may be out of date as we get faster and more reliable network speeds.

// So for balanced, file size, and transfer piece length optimizations, calculate the
// minimum piece length we can do to reach the designated pieces size. Then, if that
// piece length is less than the minimum piece length for that optimization, set it equal
// to the minimum. Setting it equal to the minimum (in that case) will increase the piece
// size which will shrink the pieces size which ensures we do not go outside of our max size.
// This ensure we can generate good piece lengths for both large and small files.

// Maximum Piece Length Across The Board, Takes Priority Over Max Pieces Sizes
// (Not Applied To Custom Lengths)
const ALL_OPT_MAX_PIECE_LENGTH: usize = 16 * 1024 * 1024;

const BALANCED_MAX_PIECES_SIZE: usize = 40000;
const BALANCED_MIN_PIECE_LENGTH: usize = 512 * 1024;

const FILE_SIZE_MAX_PIECES_SIZE: usize = 20000;
const FILE_SIZE_MIN_PIECE_LENGTH: usize = 1 * 1024 * 1024;

const TRANSFER_MAX_PIECES_SIZE: usize = 60000;
const TRANSFER_MIN_PIECE_LENGTH: usize = 1 * 1024;

/// Enumerates settings for piece length for generating a torrent file.
pub enum PieceLength {
    /// Optimize piece length for torrent file size and file transfer.
    OptBalanced,
    /// Optimize piece length for torrent file size.
    OptFileSize,
    /// Optimize piece length for torrent file transfer.
    OptTransfer,
    /// Custom piece length.
    Custom(usize),
}

/// Builder for generating a torrent file from some accessor.
pub struct MetainfoBuilder<'a> {
    root: BencodeMut<'a>,
    info: InfoBuilder<'a>
}

impl<'a> MetainfoBuilder<'a> {
    /// Create a new MetainfoBuilder with some default values set.
    pub fn new() -> MetainfoBuilder<'a> {
        MetainfoBuilder {
            root: BencodeMut::new_dict(),
            info: InfoBuilder::new()
        }
    }

    /// Set or unset the main tracker that this torrent file points to.
    pub fn set_main_tracker(mut self, opt_tracker_url: Option<&'a str>) -> MetainfoBuilder<'a> {
        {
            let dict_access = self.root.dict_mut().unwrap();
            opt_tracker_url
                .and_then(|tracker_url| dict_access.insert(parse::ANNOUNCE_URL_KEY.into(), ben_bytes!(tracker_url)))
                .or_else(|| dict_access.remove(parse::ANNOUNCE_URL_KEY));
        }

        self
    }

    /// Set or unset the creation date for the torrent.
    pub fn set_creation_date(mut self, opt_secs_epoch: Option<i64>) -> MetainfoBuilder<'a> {
        {
            let dict_access = self.root.dict_mut().unwrap();
            opt_secs_epoch
                .and_then(|secs_epoch| dict_access.insert(parse::CREATION_DATE_KEY.into(), ben_int!(secs_epoch)))
                .or_else(|| dict_access.remove(parse::CREATION_DATE_KEY));
        }

        self
    }

    /// Set or unset a comment for the torrent file.
    pub fn set_comment(mut self, opt_comment: Option<&'a str>) -> MetainfoBuilder<'a> {
        {
            let dict_access = self.root.dict_mut().unwrap();
            opt_comment
                .and_then(|comment| dict_access.insert(parse::COMMENT_KEY.into(), ben_bytes!(comment)))
                .or_else(|| dict_access.remove(parse::COMMENT_KEY));
        }

        self
    }

    /// Set or unset the created by for the torrent file.
    pub fn set_created_by(mut self, opt_created_by: Option<&'a str>) -> MetainfoBuilder<'a> {
        {
            let dict_access = self.root.dict_mut().unwrap();
            opt_created_by
                .and_then(|created_by| dict_access.insert(parse::CREATED_BY_KEY.into(), ben_bytes!(created_by)))
                .or_else(|| dict_access.remove(parse::CREATED_BY_KEY));
        }

        self
    }

    /// Set or unset the private flag for the torrent file.
    pub fn set_private_flag(mut self, opt_is_private: Option<bool>) -> MetainfoBuilder<'a> {
        self.info = self.info.set_private_flag(opt_is_private);

        self
    }

    /// Sets the piece length for the torrent file.
    pub fn set_piece_length(mut self, piece_length: PieceLength) -> MetainfoBuilder<'a> {
        self.info = self.info.set_piece_length(piece_length);

        self
    }

    /// Build the metainfo file from the given accessor and the number of worker threads.
    ///
    /// Panics if threads is equal to zero.
    pub fn build<A, C>(self, threads: usize, accessor: A, progress: C) -> ParseResult<Vec<u8>>
        where A: IntoAccessor,
              C: FnMut(f64) + Send + 'static
    {
        let accessor = try!(accessor.into_accessor());

        build_with_accessor(threads, accessor, progress, Some(self.root), self.info.info, self.info.piece_length)
    }
}

// ----------------------------------------------------------------------------//

/// Builder for generating an info dictionary file from some accessor.
pub struct InfoBuilder<'a> {
    info:         BencodeMut<'a>,
    // Stored outside of root as some of the variants need the total
    // file sizes in order for the final piece length to be calculated.
    piece_length: PieceLength
}

impl<'a> InfoBuilder<'a> {
    pub fn new() -> InfoBuilder<'a> {
        InfoBuilder{ info: BencodeMut::new_dict(), piece_length: PieceLength::OptBalanced }
    }

    /// Set or unset the private flag for the torrent file.
    pub fn set_private_flag(mut self, opt_is_private: Option<bool>) -> InfoBuilder<'a> {
        let opt_numeric_is_private = opt_is_private.map(|is_private| if is_private{ 1 } else { 0 });

        {
            let dict_access = self.info.dict_mut().unwrap();
            opt_numeric_is_private
                .and_then(|numeric_is_private| dict_access.insert(parse::PRIVATE_KEY.into(), ben_int!(numeric_is_private)))
                .or_else(|| dict_access.remove(parse::PRIVATE_KEY));
        }

        self
    }

    /// Sets the piece length for the torrent file.
    pub fn set_piece_length(mut self, piece_length: PieceLength) -> InfoBuilder<'a> {
        self.piece_length = piece_length;

        self
    }

    /// Build the metainfo file from the given accessor and the number of worker threads.
    ///
    /// Panics if threads is equal to zero.
    pub fn build<A, C>(self, threads: usize, accessor: A, progress: C) -> ParseResult<Vec<u8>>
        where A: IntoAccessor,
              C: FnMut(f64) + Send + 'static
    {
        let accessor = try!(accessor.into_accessor());

        build_with_accessor(threads, accessor, progress, None, self.info, self.piece_length)
    }
}

// ----------------------------------------------------------------------------//

fn build_with_accessor<'a, A, C>(threads:       usize,
                                accessor:       A,
                                progress:       C,
                                opt_root:       Option<BencodeMut<'a>>,
                                info:           BencodeMut<'a>,
                                piece_length:   PieceLength) -> ParseResult<Vec<u8>>
    where A: Accessor,
          C: FnMut(f64) + Send + 'static {
        if threads == 0 {
            panic!("bip_metainfo: Cannot Build Metainfo File With threads == 0");
        }

        // Collect all of the file information into a list
        let mut files_info = Vec::new();
        try!(accessor.access_metadata(|len, path| {
            let path_list: Vec<String> = path.iter()
                .map(|os_str| os_str.to_string_lossy().into_owned())
                .collect();

            files_info.push((len, path_list));
        }));

        // Build the pieces for the data our accessor is pointing at
        let total_files_len = files_info.iter().fold(0, |acc, nex| acc + nex.0);
        let piece_length = determine_piece_length(total_files_len, piece_length);
        let total_num_pieces = ((total_files_len as f64) / (piece_length as f64)).ceil() as u64;
        let pieces_list = try!(worker::start_hasher_workers(&accessor,
                                                            piece_length,
                                                            total_num_pieces,
                                                            threads,
                                                            progress));
        let pieces = map_pieces_list(pieces_list.into_iter().map(|(_, piece)| piece));

        let mut single_file_name = String::new();
        let access_directory = accessor.access_directory().map(|path| path.to_string_lossy());

        // Move these below access directory for borrow checker
        let opt_root = opt_root;
        let mut info = info;

        // Update the info bencode with values
        {
            let info_access = info.dict_mut().unwrap();

            info_access.insert(parse::PIECE_LENGTH_KEY.into(), ben_int!(piece_length as i64));
            info_access.insert(parse::PIECES_KEY.into(), ben_bytes!(&pieces[..]));

            // If the accessor specifies a directory OR there are mutliple files, we will build a multi file torrent
            // If the directory is not present but there are multiple files, the direcotry field will be set to empty
            match (&access_directory, files_info.len() > 1) {
                (&Some(ref directory), _) => {
                    let mut bencode_files = BencodeMut::new_list();

                    {
                        let bencode_files_access = bencode_files.list_mut().unwrap();

                        // Multi File
                        for &(len, ref path) in files_info.iter() {
                            let mut bencode_path = BencodeMut::new_list();

                            {
                                let bencode_path_access = bencode_path.list_mut().unwrap();

                                for path_element in path.iter() {
                                    bencode_path_access.push(ben_bytes!(&path_element[..]));
                                }
                            }

                            bencode_files_access.push(ben_map!{
                                parse::LENGTH_KEY => ben_int!(len as i64),
                                parse::PATH_KEY   => bencode_path
                            });
                        }
                    }

                    info_access.insert(parse::NAME_KEY.into(), ben_bytes!(directory.as_ref()));
                    info_access.insert(parse::FILES_KEY.into(), bencode_files);
                }
                (&None, true) => {
                    let mut bencode_files = BencodeMut::new_list();

                    {
                        let bencode_files_access = bencode_files.list_mut().unwrap();

                        // Multi File
                        for &(len, ref path) in files_info.iter() {
                            let mut bencode_path = BencodeMut::new_list();

                            {
                                let bencode_path_access = bencode_path.list_mut().unwrap();

                                for path_element in path.iter() {
                                    bencode_path_access.push(ben_bytes!(&path_element[..]));
                                }
                            }

                            bencode_files_access.push(ben_map!{
                                parse::LENGTH_KEY => ben_int!(len as i64),
                                parse::PATH_KEY   => bencode_path
                            });
                        }
                    }

                    info_access.insert(parse::NAME_KEY.into(), ben_bytes!(""));
                    info_access.insert(parse::FILES_KEY.into(), bencode_files);
                }
                (&None, false) => {
                    // Single File
                    for name_component in files_info[0].1.iter() {
                        single_file_name.push_str(name_component);
                    }

                    info_access.insert(parse::LENGTH_KEY.into(), ben_int!(files_info[0].0 as i64));
                    info_access.insert(parse::NAME_KEY.into(), ben_bytes!(&single_file_name[..]));
                }
            }
        }

        if let Some(mut root) = opt_root {
            root.dict_mut().unwrap().insert(parse::INFO_KEY.into(), info);

            Ok(root.encode())
        } else {
            Ok(info.encode())
        }
}

/// Calculate the final piece length given the total file size and piece length strategy.
///
/// Lower piece length will result in a bigger file but better transfer reliability and vice versa.
fn determine_piece_length(total_file_size: u64, piece_length: PieceLength) -> usize {
    match piece_length {
        PieceLength::Custom(len) => len,
        PieceLength::OptBalanced => {
            calculate_piece_length(total_file_size,
                                   BALANCED_MAX_PIECES_SIZE,
                                   BALANCED_MIN_PIECE_LENGTH)
        }
        PieceLength::OptFileSize => {
            calculate_piece_length(total_file_size,
                                   FILE_SIZE_MAX_PIECES_SIZE,
                                   FILE_SIZE_MIN_PIECE_LENGTH)
        }
        PieceLength::OptTransfer => {
            calculate_piece_length(total_file_size,
                                   TRANSFER_MAX_PIECES_SIZE,
                                   TRANSFER_MIN_PIECE_LENGTH)
        }
    }
}

/// Calculate the minimum power of 2 piece length for the given max pieces size and total file size.
fn calculate_piece_length(total_file_size: u64,
                          max_pieces_size: usize,
                          min_piece_length: usize)
                          -> usize {
    let num_pieces = (max_pieces_size as f64) / (sha::SHA_HASH_LEN as f64);
    let piece_length = ((total_file_size as f64) / num_pieces + 0.5) as usize;

    let pot_piece_length = piece_length.next_power_of_two();

    match (pot_piece_length > min_piece_length, pot_piece_length < ALL_OPT_MAX_PIECE_LENGTH) {
        (true, true) => pot_piece_length,
        (false, _) => min_piece_length,
        (_, false) => ALL_OPT_MAX_PIECE_LENGTH,
    }
}
/// Map the pieces list into a list of bytes (byte string).
fn map_pieces_list<I>(pieces: I) -> Vec<u8>
    where I: Iterator<Item = ShaHash> + ExactSizeIterator
{
    let mut concated_pieces = Vec::with_capacity(pieces.len() * sha::SHA_HASH_LEN);
    for piece in pieces {
        concated_pieces.extend_from_slice(piece.as_ref());
    }

    concated_pieces
}
<commit_msg>[bip_metainfo] Added method `set_trackers` to the builder (#143)<commit_after>use std::iter::ExactSizeIterator;

use bip_bencode::{BencodeMut, BMutAccess};
use bip_util::sha::{self, ShaHash};

use accessor::{Accessor, IntoAccessor};
use error::ParseResult;
use parse;

mod buffer;
mod worker;

// Piece length is inversly related to the file size.
// Transfer reliability is inversly related to the piece length.
// Transfer reliability is directly related to the file size.

// These statements hold even today, although the piece lengths that were historically
// recommended may be out of date as we get faster and more reliable network speeds.

// So for balanced, file size, and transfer piece length optimizations, calculate the
// minimum piece length we can do to reach the designated pieces size. Then, if that
// piece length is less than the minimum piece length for that optimization, set it equal
// to the minimum. Setting it equal to the minimum (in that case) will increase the piece
// size which will shrink the pieces size which ensures we do not go outside of our max size.
// This ensure we can generate good piece lengths for both large and small files.

// Maximum Piece Length Across The Board, Takes Priority Over Max Pieces Sizes
// (Not Applied To Custom Lengths)
const ALL_OPT_MAX_PIECE_LENGTH: usize = 16 * 1024 * 1024;

const BALANCED_MAX_PIECES_SIZE: usize = 40000;
const BALANCED_MIN_PIECE_LENGTH: usize = 512 * 1024;

const FILE_SIZE_MAX_PIECES_SIZE: usize = 20000;
const FILE_SIZE_MIN_PIECE_LENGTH: usize = 1 * 1024 * 1024;

const TRANSFER_MAX_PIECES_SIZE: usize = 60000;
const TRANSFER_MIN_PIECE_LENGTH: usize = 1 * 1024;

/// Enumerates settings for piece length for generating a torrent file.
pub enum PieceLength {
    /// Optimize piece length for torrent file size and file transfer.
    OptBalanced,
    /// Optimize piece length for torrent file size.
    OptFileSize,
    /// Optimize piece length for torrent file transfer.
    OptTransfer,
    /// Custom piece length.
    Custom(usize),
}

/// Builder for generating a torrent file from some accessor.
pub struct MetainfoBuilder<'a> {
    root: BencodeMut<'a>,
    info: InfoBuilder<'a>
}

impl<'a> MetainfoBuilder<'a> {
    /// Create a new MetainfoBuilder with some default values set.
    pub fn new() -> MetainfoBuilder<'a> {
        MetainfoBuilder {
            root: BencodeMut::new_dict(),
            info: InfoBuilder::new()
        }
    }

    /// Set announce-list content
    pub fn set_trackers(mut self, opt_trackers: Option<&'a Vec<Vec<String>>>) -> MetainfoBuilder<'a> {
        {
            let dict_access = self.root.dict_mut().unwrap();

            if let Some(groups) = opt_trackers {
                let mut list = BencodeMut::new_list();

                {
                    let list_access = list.list_mut().unwrap();

                    for group in groups.iter() {
                        let mut tracker_list = BencodeMut::new_list();

                        {
                            let tracker_list_access = tracker_list.list_mut().unwrap();

                            for tracker_url in group.iter() {
                                tracker_list_access.push(ben_bytes!(&tracker_url[..]));
                            }
                        }

                        list_access.push(tracker_list);
                    }
                }

                dict_access.insert(parse::ANNOUNCE_LIST_KEY.into(), list);
            } else {
                dict_access.remove(parse::ANNOUNCE_LIST_KEY);
            }
        }

        self
    }

    /// Set or unset the main tracker that this torrent file points to.
    pub fn set_main_tracker(mut self, opt_tracker_url: Option<&'a str>) -> MetainfoBuilder<'a> {
        {
            let dict_access = self.root.dict_mut().unwrap();
            opt_tracker_url
                .and_then(|tracker_url| dict_access.insert(parse::ANNOUNCE_URL_KEY.into(), ben_bytes!(tracker_url)))
                .or_else(|| dict_access.remove(parse::ANNOUNCE_URL_KEY));
        }

        self
    }

    /// Set or unset the creation date for the torrent.
    pub fn set_creation_date(mut self, opt_secs_epoch: Option<i64>) -> MetainfoBuilder<'a> {
        {
            let dict_access = self.root.dict_mut().unwrap();
            opt_secs_epoch
                .and_then(|secs_epoch| dict_access.insert(parse::CREATION_DATE_KEY.into(), ben_int!(secs_epoch)))
                .or_else(|| dict_access.remove(parse::CREATION_DATE_KEY));
        }

        self
    }

    /// Set or unset a comment for the torrent file.
    pub fn set_comment(mut self, opt_comment: Option<&'a str>) -> MetainfoBuilder<'a> {
        {
            let dict_access = self.root.dict_mut().unwrap();
            opt_comment
                .and_then(|comment| dict_access.insert(parse::COMMENT_KEY.into(), ben_bytes!(comment)))
                .or_else(|| dict_access.remove(parse::COMMENT_KEY));
        }

        self
    }

    /// Set or unset the created by for the torrent file.
    pub fn set_created_by(mut self, opt_created_by: Option<&'a str>) -> MetainfoBuilder<'a> {
        {
            let dict_access = self.root.dict_mut().unwrap();
            opt_created_by
                .and_then(|created_by| dict_access.insert(parse::CREATED_BY_KEY.into(), ben_bytes!(created_by)))
                .or_else(|| dict_access.remove(parse::CREATED_BY_KEY));
        }

        self
    }

    /// Set or unset the private flag for the torrent file.
    pub fn set_private_flag(mut self, opt_is_private: Option<bool>) -> MetainfoBuilder<'a> {
        self.info = self.info.set_private_flag(opt_is_private);

        self
    }

    /// Sets the piece length for the torrent file.
    pub fn set_piece_length(mut self, piece_length: PieceLength) -> MetainfoBuilder<'a> {
        self.info = self.info.set_piece_length(piece_length);

        self
    }

    /// Build the metainfo file from the given accessor and the number of worker threads.
    ///
    /// Panics if threads is equal to zero.
    pub fn build<A, C>(self, threads: usize, accessor: A, progress: C) -> ParseResult<Vec<u8>>
        where A: IntoAccessor,
              C: FnMut(f64) + Send + 'static
    {
        let accessor = try!(accessor.into_accessor());

        build_with_accessor(threads, accessor, progress, Some(self.root), self.info.info, self.info.piece_length)
    }
}

// ----------------------------------------------------------------------------//

/// Builder for generating an info dictionary file from some accessor.
pub struct InfoBuilder<'a> {
    info:         BencodeMut<'a>,
    // Stored outside of root as some of the variants need the total
    // file sizes in order for the final piece length to be calculated.
    piece_length: PieceLength
}

impl<'a> InfoBuilder<'a> {
    pub fn new() -> InfoBuilder<'a> {
        InfoBuilder{ info: BencodeMut::new_dict(), piece_length: PieceLength::OptBalanced }
    }

    /// Set or unset the private flag for the torrent file.
    pub fn set_private_flag(mut self, opt_is_private: Option<bool>) -> InfoBuilder<'a> {
        let opt_numeric_is_private = opt_is_private.map(|is_private| if is_private{ 1 } else { 0 });

        {
            let dict_access = self.info.dict_mut().unwrap();
            opt_numeric_is_private
                .and_then(|numeric_is_private| dict_access.insert(parse::PRIVATE_KEY.into(), ben_int!(numeric_is_private)))
                .or_else(|| dict_access.remove(parse::PRIVATE_KEY));
        }

        self
    }

    /// Sets the piece length for the torrent file.
    pub fn set_piece_length(mut self, piece_length: PieceLength) -> InfoBuilder<'a> {
        self.piece_length = piece_length;

        self
    }

    /// Build the metainfo file from the given accessor and the number of worker threads.
    ///
    /// Panics if threads is equal to zero.
    pub fn build<A, C>(self, threads: usize, accessor: A, progress: C) -> ParseResult<Vec<u8>>
        where A: IntoAccessor,
              C: FnMut(f64) + Send + 'static
    {
        let accessor = try!(accessor.into_accessor());

        build_with_accessor(threads, accessor, progress, None, self.info, self.piece_length)
    }
}

// ----------------------------------------------------------------------------//

fn build_with_accessor<'a, A, C>(threads:       usize,
                                accessor:       A,
                                progress:       C,
                                opt_root:       Option<BencodeMut<'a>>,
                                info:           BencodeMut<'a>,
                                piece_length:   PieceLength) -> ParseResult<Vec<u8>>
    where A: Accessor,
          C: FnMut(f64) + Send + 'static {
        if threads == 0 {
            panic!("bip_metainfo: Cannot Build Metainfo File With threads == 0");
        }

        // Collect all of the file information into a list
        let mut files_info = Vec::new();
        try!(accessor.access_metadata(|len, path| {
            let path_list: Vec<String> = path.iter()
                .map(|os_str| os_str.to_string_lossy().into_owned())
                .collect();

            files_info.push((len, path_list));
        }));

        // Build the pieces for the data our accessor is pointing at
        let total_files_len = files_info.iter().fold(0, |acc, nex| acc + nex.0);
        let piece_length = determine_piece_length(total_files_len, piece_length);
        let total_num_pieces = ((total_files_len as f64) / (piece_length as f64)).ceil() as u64;
        let pieces_list = try!(worker::start_hasher_workers(&accessor,
                                                            piece_length,
                                                            total_num_pieces,
                                                            threads,
                                                            progress));
        let pieces = map_pieces_list(pieces_list.into_iter().map(|(_, piece)| piece));

        let mut single_file_name = String::new();
        let access_directory = accessor.access_directory().map(|path| path.to_string_lossy());

        // Move these below access directory for borrow checker
        let opt_root = opt_root;
        let mut info = info;

        // Update the info bencode with values
        {
            let info_access = info.dict_mut().unwrap();

            info_access.insert(parse::PIECE_LENGTH_KEY.into(), ben_int!(piece_length as i64));
            info_access.insert(parse::PIECES_KEY.into(), ben_bytes!(&pieces[..]));

            // If the accessor specifies a directory OR there are mutliple files, we will build a multi file torrent
            // If the directory is not present but there are multiple files, the direcotry field will be set to empty
            match (&access_directory, files_info.len() > 1) {
                (&Some(ref directory), _) => {
                    let mut bencode_files = BencodeMut::new_list();

                    {
                        let bencode_files_access = bencode_files.list_mut().unwrap();

                        // Multi File
                        for &(len, ref path) in files_info.iter() {
                            let mut bencode_path = BencodeMut::new_list();

                            {
                                let bencode_path_access = bencode_path.list_mut().unwrap();

                                for path_element in path.iter() {
                                    bencode_path_access.push(ben_bytes!(&path_element[..]));
                                }
                            }

                            bencode_files_access.push(ben_map!{
                                parse::LENGTH_KEY => ben_int!(len as i64),
                                parse::PATH_KEY   => bencode_path
                            });
                        }
                    }

                    info_access.insert(parse::NAME_KEY.into(), ben_bytes!(directory.as_ref()));
                    info_access.insert(parse::FILES_KEY.into(), bencode_files);
                }
                (&None, true) => {
                    let mut bencode_files = BencodeMut::new_list();

                    {
                        let bencode_files_access = bencode_files.list_mut().unwrap();

                        // Multi File
                        for &(len, ref path) in files_info.iter() {
                            let mut bencode_path = BencodeMut::new_list();

                            {
                                let bencode_path_access = bencode_path.list_mut().unwrap();

                                for path_element in path.iter() {
                                    bencode_path_access.push(ben_bytes!(&path_element[..]));
                                }
                            }

                            bencode_files_access.push(ben_map!{
                                parse::LENGTH_KEY => ben_int!(len as i64),
                                parse::PATH_KEY   => bencode_path
                            });
                        }
                    }

                    info_access.insert(parse::NAME_KEY.into(), ben_bytes!(""));
                    info_access.insert(parse::FILES_KEY.into(), bencode_files);
                }
                (&None, false) => {
                    // Single File
                    for name_component in files_info[0].1.iter() {
                        single_file_name.push_str(name_component);
                    }

                    info_access.insert(parse::LENGTH_KEY.into(), ben_int!(files_info[0].0 as i64));
                    info_access.insert(parse::NAME_KEY.into(), ben_bytes!(&single_file_name[..]));
                }
            }
        }

        if let Some(mut root) = opt_root {
            root.dict_mut().unwrap().insert(parse::INFO_KEY.into(), info);

            Ok(root.encode())
        } else {
            Ok(info.encode())
        }
}

/// Calculate the final piece length given the total file size and piece length strategy.
///
/// Lower piece length will result in a bigger file but better transfer reliability and vice versa.
fn determine_piece_length(total_file_size: u64, piece_length: PieceLength) -> usize {
    match piece_length {
        PieceLength::Custom(len) => len,
        PieceLength::OptBalanced => {
            calculate_piece_length(total_file_size,
                                   BALANCED_MAX_PIECES_SIZE,
                                   BALANCED_MIN_PIECE_LENGTH)
        }
        PieceLength::OptFileSize => {
            calculate_piece_length(total_file_size,
                                   FILE_SIZE_MAX_PIECES_SIZE,
                                   FILE_SIZE_MIN_PIECE_LENGTH)
        }
        PieceLength::OptTransfer => {
            calculate_piece_length(total_file_size,
                                   TRANSFER_MAX_PIECES_SIZE,
                                   TRANSFER_MIN_PIECE_LENGTH)
        }
    }
}

/// Calculate the minimum power of 2 piece length for the given max pieces size and total file size.
fn calculate_piece_length(total_file_size: u64,
                          max_pieces_size: usize,
                          min_piece_length: usize)
                          -> usize {
    let num_pieces = (max_pieces_size as f64) / (sha::SHA_HASH_LEN as f64);
    let piece_length = ((total_file_size as f64) / num_pieces + 0.5) as usize;

    let pot_piece_length = piece_length.next_power_of_two();

    match (pot_piece_length > min_piece_length, pot_piece_length < ALL_OPT_MAX_PIECE_LENGTH) {
        (true, true) => pot_piece_length,
        (false, _) => min_piece_length,
        (_, false) => ALL_OPT_MAX_PIECE_LENGTH,
    }
}
/// Map the pieces list into a list of bytes (byte string).
fn map_pieces_list<I>(pieces: I) -> Vec<u8>
    where I: Iterator<Item = ShaHash> + ExactSizeIterator
{
    let mut concated_pieces = Vec::with_capacity(pieces.len() * sha::SHA_HASH_LEN);
    for piece in pieces {
        concated_pieces.extend_from_slice(piece.as_ref());
    }

    concated_pieces
}
<|endoftext|>


<commit_before><commit_msg>fixed bug in IndirectIndexing address mode<commit_after><|endoftext|>


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

extern crate glob;
extern crate serde;
extern crate serde_json;

use self::glob::glob;
use self::serde::{Serialize, Deserialize};

use std::io::{Read, Write};
use std::fs::File;
use std::vec::Vec;

/*===============================================================================================*/
/*------CONFIG STRUCT----------------------------------------------------------------------------*/
/*===============================================================================================*/

#[derive (Clone)]
pub struct Config {

    // Public
    /// The name of the config file.
    pub name: String,
    /// The path to the config file.
    pub path: String
}

/*===============================================================================================*/
/*------CONFIGMANAGER STRUCT---------------------------------------------------------------------*/
/*===============================================================================================*/

/// Handles the application config.
///
/// It is resposible for loading the app config, and allowing other modules easy access to that data.
/// It is also used for saving the app config.
#[derive (Clone, Default)]
pub struct ConfigManager {

    // Public
    /// The path to the config directory.
    pub config_dir: String,

    // Private
    _config_list: Vec<Config>
}

/*===============================================================================================*/
/*------CONFIGMANAGER PUBLIC METHODS-------------------------------------------------------------*/
/*===============================================================================================*/

impl ConfigManager {

    /// Queries the config directory, and stores a list of configs.
    pub fn query_config_dir (&mut self) {

        // Clear the old config list
        self._config_list.clear ();

        info! ("Searching for config files...");

        // Recurse through all items in the config directory
        for path in glob (&format! ("{}/*{}", &self.config_dir, ".json")).unwrap ().filter_map (Result::ok) {

            self._config_list.push (Config {name: path.file_stem ().unwrap ().to_str ().unwrap ().to_string (),
                                            path: path.to_str ().unwrap ().to_string ()});

            info! ("Found: {:?}", &path.file_name ().unwrap ());
        }

        // If list is empty, print empty
        // Otherwise, print searching complete
        if self._config_list.is_empty () {
            info! ("No config files found.");
        }

        else {
            info! ("Config searching complete.");
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Loads a config of a given name.
    ///
    /// The config file is then converted into the type `T`. `T` must derive both the
    /// [`Serialize`] (http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html) and
    /// [`Deserialize`] (http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html) traits.
    ///
    /// If this fails, an [`Err`] (https://doc.rust-lang.org/std/result/) is returned.
    ///
    /// # Return value
    /// A result containing the config struct `T`.
    pub fn load_config<T: Serialize + Deserialize> (&self, config_name: &str) -> Result<T, ()> {

        debug! ("Loading config file with name: '{}'", config_name);

        for item in &self._config_list {

            if item.name == config_name {

                let mut f = File::open (&item.path).unwrap ();
                let mut s = String::new ();

                f.read_to_string (&mut s).unwrap ();
                return Ok (serde_json::from_str::<T> (&s).unwrap ());
            }
        }

        warn! ("Could not find config file: '{}'.
                Try creating it first.", config_name);
        Err (())
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Saves a config of a given name.
    pub fn save_config<T: Serialize + Deserialize> (&self, config_name: &str, data: &T) -> Result<(), ()> {

        debug! ("Saving config file with name: '{}'", config_name);

        for item in &self._config_list {

            if item.name == config_name {

                let mut f = File::create (&item.path).unwrap ();
                f.write (serde_json::to_string_pretty (&data).unwrap ().as_bytes ()).unwrap ();
                return Ok (())
            }
        }

        warn! ("Could not find config file: '{}'.
                Try creating it first.", config_name);
        Err (())
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Check if a config file exists.
    pub fn config_exists (&self, config_name: &str) -> bool {

        for item in &self._config_list {

            if item.name == config_name {
                return true;
            }
        }

        false
    }

/*===============================================================================================*/
/*------CONFIGMANAGER PUBLIC STATIC METHODS------------------------------------------------------*/
/*===============================================================================================*/

    /// Returns a new instance of the config manager.
    ///
    /// # Default values
    /// * `config_dir` - "config".to_string ()
    ///
    /// # Return value
    /// A new config manager instance.
    pub fn new () -> ConfigManager {

        ConfigManager {config_dir: "config".to_string (),
                       _config_list: Vec::new ()}
    }
}
<commit_msg>Added a method for creating a new config file<commit_after>/*===============================================================================================*/
// Copyright 2016 Kyle Finlay
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*===============================================================================================*/

extern crate glob;
extern crate serde;
extern crate serde_json;

use self::glob::glob;
use self::serde::{Serialize, Deserialize};

use std::io::{Read, Write};
use std::fs::File;
use std::vec::Vec;

/*===============================================================================================*/
/*------CONFIG STRUCT----------------------------------------------------------------------------*/
/*===============================================================================================*/

#[derive (Clone)]
pub struct Config {

    // Public
    /// The name of the config file.
    pub name: String,
    /// The path to the config file.
    pub path: String
}

/*===============================================================================================*/
/*------CONFIGMANAGER STRUCT---------------------------------------------------------------------*/
/*===============================================================================================*/

/// Handles the application config.
///
/// It is resposible for loading the app config, and allowing other modules easy access to that data.
/// It is also used for saving the app config.
#[derive (Clone, Default)]
pub struct ConfigManager {

    // Public
    /// The path to the config directory.
    pub config_dir: String,

    // Private
    _config_list: Vec<Config>
}

/*===============================================================================================*/
/*------CONFIGMANAGER PUBLIC METHODS-------------------------------------------------------------*/
/*===============================================================================================*/

impl ConfigManager {

    /// Queries the config directory, and stores a list of configs.
    pub fn query_config_dir (&mut self) {

        // Clear the old config list
        self._config_list.clear ();

        info! ("Searching for config files...");

        // Recurse through all items in the config directory
        for path in glob (&format! ("{}/*{}", &self.config_dir, ".json")).unwrap ().filter_map (Result::ok) {

            self._config_list.push (Config {name: path.file_stem ().unwrap ().to_str ().unwrap ().to_string (),
                                            path: path.to_str ().unwrap ().to_string ()});

            info! ("Found: {:?}", &path.file_name ().unwrap ());
        }

        // If list is empty, print empty
        // Otherwise, print searching complete
        if self._config_list.is_empty () {
            info! ("No config files found.");
        }

        else {
            info! ("Config searching complete.");
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Creates a new config with given name.
    pub fn create_config<T: Serialize + Deserialize + Default> (&mut self, config_name: &str) {

        debug! ("Creating config file with name: '{}'", config_name);

        let mut f = File::create (format! ("{}/{}.json", &self.config_dir, config_name)).unwrap ();
        f.write (serde_json::to_string_pretty (&T::default ()).unwrap ().as_bytes ()).unwrap ();

        self._config_list.push (Config {name: config_name.to_string (),
                                        path: format! ("{}/{}.json", &self.config_dir, config_name)});
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Loads a config of a given name.
    ///
    /// The config file is then converted into the type `T`. `T` must derive both the
    /// [`Serialize`] (http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html) and
    /// [`Deserialize`] (http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html) traits.
    ///
    /// If this fails, an [`Err`] (https://doc.rust-lang.org/std/result/) is returned.
    ///
    /// # Return value
    /// A result containing the config struct `T`.
    pub fn load_config<T: Serialize + Deserialize> (&self, config_name: &str) -> Result<T, ()> {

        debug! ("Loading config file with name: '{}'", config_name);

        for item in &self._config_list {

            if item.name == config_name {

                let mut f = File::open (&item.path).unwrap ();
                let mut s = String::new ();

                f.read_to_string (&mut s).unwrap ();
                return Ok (serde_json::from_str::<T> (&s).unwrap ());
            }
        }

        warn! ("Could not find config file: '{}'.
                Try creating it first.", config_name);
        Err (())
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Saves a config of a given name.
    pub fn save_config<T: Serialize + Deserialize> (&self, config_name: &str, data: &T) -> Result<(), ()> {

        debug! ("Saving config file with name: '{}'", config_name);

        for item in &self._config_list {

            if item.name == config_name {

                let mut f = File::create (&item.path).unwrap ();
                f.write (serde_json::to_string_pretty (&data).unwrap ().as_bytes ()).unwrap ();
                return Ok (())
            }
        }

        warn! ("Could not find config file: '{}'.
                Try creating it first.", config_name);
        Err (())
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Check if a config file exists.
    pub fn config_exists (&self, config_name: &str) -> bool {

        for item in &self._config_list {

            if item.name == config_name {
                return true;
            }
        }

        false
    }

/*===============================================================================================*/
/*------CONFIGMANAGER PUBLIC STATIC METHODS------------------------------------------------------*/
/*===============================================================================================*/

    /// Returns a new instance of the config manager.
    ///
    /// # Default values
    /// * `config_dir` - "config".to_string ()
    ///
    /// # Return value
    /// A new config manager instance.
    pub fn new () -> ConfigManager {

        ConfigManager {config_dir: "config".to_string (),
                       _config_list: Vec::new ()}
    }
}
<|endoftext|>


<commit_before>/// Semantics for a piece of error information
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
#[cfg(feature = "error-context")]
pub enum ContextKind {
    /// The cause of the error
    InvalidSubcommand,
    /// The cause of the error
    InvalidArg,
    /// Existing arguments
    PriorArg,
    /// Accepted subcommands
    ValidSubcommand,
    /// Accepted values
    ValidValue,
    /// Rejected values
    InvalidValue,
    /// Number of values present
    ActualNumValues,
    /// Number of allowed values
    ExpectedNumValues,
    /// Minimum number of allowed values
    MinValues,
    /// Potential fix for the user
    SuggestedCommand,
    /// Potential fix for the user
    SuggestedSubcommand,
    /// Potential fix for the user
    SuggestedArg,
    /// Potential fix for the user
    SuggestedValue,
    /// Trailing argument
    TrailingArg,
    /// Potential fix for the user
    Suggested,
    /// A usage string
    Usage,
    /// An opaque message to the user
    Custom,
}

impl ContextKind {
    /// End-user description of the error case, where relevant
    pub fn as_str(self) -> Option<&'static str> {
        match self {
            Self::InvalidSubcommand => Some("Invalid Subcommand"),
            Self::InvalidArg => Some("Invalid Argument"),
            Self::PriorArg => Some("Prior Argument"),
            Self::ValidSubcommand => Some("Value Subcommand"),
            Self::ValidValue => Some("Value Value"),
            Self::InvalidValue => Some("Invalid Value"),
            Self::ActualNumValues => Some("Actual Number of Values"),
            Self::ExpectedNumValues => Some("Expected Number of Values"),
            Self::MinValues => Some("Minimum Number of Values"),
            Self::SuggestedCommand => Some("Suggested Command"),
            Self::SuggestedSubcommand => Some("Suggested Subcommand"),
            Self::SuggestedArg => Some("Suggested Argument"),
            Self::SuggestedValue => Some("Suggested Value"),
            Self::TrailingArg => Some("Trailing Argument"),
            Self::Suggested => Some("Suggested"),
            Self::Usage => None,
            Self::Custom => None,
        }
    }
}

impl std::fmt::Display for ContextKind {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.as_str().unwrap_or_default().fmt(f)
    }
}

/// A piece of error information
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
#[cfg(feature = "error-context")]
pub enum ContextValue {
    /// [`ContextKind`] is self-sufficient, no additional information needed
    None,
    /// A single value
    Bool(bool),
    /// A single value
    String(String),
    /// Many values
    Strings(Vec<String>),
    /// A single value
    StyledStr(crate::builder::StyledStr),
    /// many value
    StyledStrs(Vec<crate::builder::StyledStr>),
    /// A single value
    Number(isize),
}

impl std::fmt::Display for ContextValue {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::None => "".fmt(f),
            Self::Bool(v) => v.fmt(f),
            Self::String(v) => v.fmt(f),
            Self::Strings(v) => v.join(", ").fmt(f),
            Self::StyledStr(v) => v.fmt(f),
            Self::StyledStrs(v) => {
                for (i, v) in v.iter().enumerate() {
                    if i != 0 {
                        ", ".fmt(f)?;
                    }
                    v.fmt(f)?;
                }
                Ok(())
            }
            Self::Number(v) => v.fmt(f),
        }
    }
}
<commit_msg>fix: ContextKind.as_str() spellings<commit_after>/// Semantics for a piece of error information
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
#[cfg(feature = "error-context")]
pub enum ContextKind {
    /// The cause of the error
    InvalidSubcommand,
    /// The cause of the error
    InvalidArg,
    /// Existing arguments
    PriorArg,
    /// Accepted subcommands
    ValidSubcommand,
    /// Accepted values
    ValidValue,
    /// Rejected values
    InvalidValue,
    /// Number of values present
    ActualNumValues,
    /// Number of allowed values
    ExpectedNumValues,
    /// Minimum number of allowed values
    MinValues,
    /// Potential fix for the user
    SuggestedCommand,
    /// Potential fix for the user
    SuggestedSubcommand,
    /// Potential fix for the user
    SuggestedArg,
    /// Potential fix for the user
    SuggestedValue,
    /// Trailing argument
    TrailingArg,
    /// Potential fix for the user
    Suggested,
    /// A usage string
    Usage,
    /// An opaque message to the user
    Custom,
}

impl ContextKind {
    /// End-user description of the error case, where relevant
    pub fn as_str(self) -> Option<&'static str> {
        match self {
            Self::InvalidSubcommand => Some("Invalid Subcommand"),
            Self::InvalidArg => Some("Invalid Argument"),
            Self::PriorArg => Some("Prior Argument"),
            Self::ValidSubcommand => Some("Valid Subcommand"),
            Self::ValidValue => Some("Valid Value"),
            Self::InvalidValue => Some("Invalid Value"),
            Self::ActualNumValues => Some("Actual Number of Values"),
            Self::ExpectedNumValues => Some("Expected Number of Values"),
            Self::MinValues => Some("Minimum Number of Values"),
            Self::SuggestedCommand => Some("Suggested Command"),
            Self::SuggestedSubcommand => Some("Suggested Subcommand"),
            Self::SuggestedArg => Some("Suggested Argument"),
            Self::SuggestedValue => Some("Suggested Value"),
            Self::TrailingArg => Some("Trailing Argument"),
            Self::Suggested => Some("Suggested"),
            Self::Usage => None,
            Self::Custom => None,
        }
    }
}

impl std::fmt::Display for ContextKind {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.as_str().unwrap_or_default().fmt(f)
    }
}

/// A piece of error information
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
#[cfg(feature = "error-context")]
pub enum ContextValue {
    /// [`ContextKind`] is self-sufficient, no additional information needed
    None,
    /// A single value
    Bool(bool),
    /// A single value
    String(String),
    /// Many values
    Strings(Vec<String>),
    /// A single value
    StyledStr(crate::builder::StyledStr),
    /// many value
    StyledStrs(Vec<crate::builder::StyledStr>),
    /// A single value
    Number(isize),
}

impl std::fmt::Display for ContextValue {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::None => "".fmt(f),
            Self::Bool(v) => v.fmt(f),
            Self::String(v) => v.fmt(f),
            Self::Strings(v) => v.join(", ").fmt(f),
            Self::StyledStr(v) => v.fmt(f),
            Self::StyledStrs(v) => {
                for (i, v) in v.iter().enumerate() {
                    if i != 0 {
                        ", ".fmt(f)?;
                    }
                    v.fmt(f)?;
                }
                Ok(())
            }
            Self::Number(v) => v.fmt(f),
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>mark releases as yanked when a yank is detected<commit_after><|endoftext|>


<commit_before>use std::{
    collections::HashSet,
    iter::FromIterator,
};

use serde::{
    Deserialize,
    Serialize,
};

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
pub struct RawAccession {
    pub id: usize,
    pub urs_taxid: String,
    accession: String,
    common_name: Option<String>,
    database: String,
    external_id: String,
    function: Option<String>,
    gene_synonyms: Option<String>,
    gene: Option<String>,
    locus_tag: Option<String>,
    non_coding_id: Option<String>,
    notes: Option<String>,
    optional_id: Option<String>,
    organelle: Option<String>,
    parent_accession: Option<String>,
    products: Option<String>,
    species: Option<String>,
    standard_name: Option<String>,
    tax_string: Option<String>,
    authors: Option<String>,
    journal: Option<String>,
    pub_title: Option<String>,
    pub_id: Option<u64>,
    pubmed_id: Option<String>,
    doi: Option<String>,
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
pub struct CrossReference {
    name: String,
    external_id: String,
    optional_id: Option<String>,
    accession: String,
    non_coding_id: Option<String>,
    parent_accession: Option<String>,
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct AccessionVec {
    species: HashSet<String>,
    organelles: HashSet<String>,
    tax_strings: HashSet<String>,
    functions: HashSet<String>,
    genes: HashSet<String>,
    gene_synonyms: HashSet<String>,
    common_name: HashSet<String>,
    notes: HashSet<String>,
    locus_tags: HashSet<String>,
    standard_names: HashSet<String>,
    products: HashSet<String>,
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ReferenceVec {
    authors: HashSet<String>,
    journals: HashSet<String>,
    pub_titles: HashSet<String>,
    pub_ids: HashSet<u64>,
    pubmed_ids: HashSet<String>,
    dois: HashSet<String>,
}

impl Default for ReferenceVec {
    fn default() -> Self {
        Self {
            authors: HashSet::new(),
            journals: HashSet::new(),
            pub_titles: HashSet::new(),
            pub_ids: HashSet::new(),
            pubmed_ids: HashSet::new(),
            dois: HashSet::new(),
        }
    }
}

impl Default for AccessionVec {
    fn default() -> Self {
        Self {
            species: HashSet::new(),
            organelles: HashSet::new(),
            tax_strings: HashSet::new(),
            functions: HashSet::new(),
            genes: HashSet::new(),
            gene_synonyms: HashSet::new(),
            common_name: HashSet::new(),
            notes: HashSet::new(),
            locus_tags: HashSet::new(),
            standard_names: HashSet::new(),
            products: HashSet::new(),
        }
    }
}

impl From<RawAccession> for CrossReference {
    fn from(raw: RawAccession) -> Self {
        Self {
            name: raw.database,
            external_id: raw.external_id,
            optional_id: raw.optional_id,
            accession: raw.accession,
            non_coding_id: raw.non_coding_id,
            parent_accession: raw.parent_accession,
        }
    }
}

impl FromIterator<RawAccession> for AccessionVec {
    fn from_iter<I: IntoIterator<Item = RawAccession>>(iter: I) -> Self {
        let mut a = AccessionVec::default();

        for i in iter {
            a.species.extend(i.species.into_iter().filter(|s| !s.is_empty()));
            a.tax_strings.extend(i.tax_strings.into_iter().filter(|t| !t.is_empty()));
            a.organelles.extend(i.organelles.clone());
            a.functions.extend(i.functions.into_iter());
            a.genes.extend(i.genes.into_iter());
            a.common_name.extend(i.common_name.into_iter());
            a.notes.extend(i.notes.into_iter());
            a.locus_tags.extend(i.locus_tags.into_iter());
            a.standard_names.extend(i.standard_names.into_iter());
            a.products.extend(i.products.into_iter());

            for synonyms in i.gene_synonyms.into_iter() {
                if synonyms.contains(";") {
                    a.gene_synonyms
                        .extend(synonyms.split(";").map(|p| p.trim()).map(str::to_string))
                } else if synonyms.contains(",") {
                    a.gene_synonyms
                        .extend(synonyms.split(",").map(|p| p.trim()).map(str::to_string))
                } else {
                    a.gene_synonyms.insert(synonyms);
                }
            }
        }

        a
    }
}

impl FromIterator<RawAccession> for ReferenceVec {
    fn from_iter<I: IntoIterator<Item = RawAccession>>(iter: I) -> Self {
        let mut value = ReferenceVec::default();

        for i in iter {
            if i.authors.is_some() {
                let authors = i.authors.unwrap();
                let authors = authors.split(", ").filter(|a| !a.is_empty()).map(|s| s.to_string());
                value.authors.extend(authors);
            }

            value.journals.extend(i.journal.into_iter());
            value.pub_titles.extend(i.pub_title.into_iter().filter(|t| !t.is_empty()));
            value.pub_ids.extend(i.pub_id.into_iter());
            value.pubmed_ids.extend(i.pubmed_id.into_iter().filter(|t| !t.is_empty()));
            value.dois.extend(i.doi.into_iter().filter(|t| !t.is_empty()));
        }

        value
    }
}
<commit_msg>Filter out empty strings<commit_after>use std::{
    collections::HashSet,
    iter::FromIterator,
};

use serde::{
    Deserialize,
    Serialize,
};

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
pub struct RawAccession {
    pub id: usize,
    pub urs_taxid: String,
    accession: String,
    common_name: Option<String>,
    database: String,
    external_id: String,
    function: Option<String>,
    gene_synonyms: Option<String>,
    gene: Option<String>,
    locus_tag: Option<String>,
    non_coding_id: Option<String>,
    notes: Option<String>,
    optional_id: Option<String>,
    organelle: Option<String>,
    parent_accession: Option<String>,
    products: Option<String>,
    species: Option<String>,
    standard_name: Option<String>,
    tax_string: Option<String>,
    authors: Option<String>,
    journal: Option<String>,
    pub_title: Option<String>,
    pub_id: Option<u64>,
    pubmed_id: Option<String>,
    doi: Option<String>,
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
pub struct CrossReference {
    name: String,
    external_id: String,
    optional_id: Option<String>,
    accession: String,
    non_coding_id: Option<String>,
    parent_accession: Option<String>,
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct AccessionVec {
    species: HashSet<String>,
    organelles: HashSet<String>,
    tax_strings: HashSet<String>,
    functions: HashSet<String>,
    genes: HashSet<String>,
    gene_synonyms: HashSet<String>,
    common_name: HashSet<String>,
    notes: HashSet<String>,
    locus_tags: HashSet<String>,
    standard_names: HashSet<String>,
    products: HashSet<String>,
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ReferenceVec {
    authors: HashSet<String>,
    journals: HashSet<String>,
    pub_titles: HashSet<String>,
    pub_ids: HashSet<u64>,
    pubmed_ids: HashSet<String>,
    dois: HashSet<String>,
}

impl Default for ReferenceVec {
    fn default() -> Self {
        Self {
            authors: HashSet::new(),
            journals: HashSet::new(),
            pub_titles: HashSet::new(),
            pub_ids: HashSet::new(),
            pubmed_ids: HashSet::new(),
            dois: HashSet::new(),
        }
    }
}

impl Default for AccessionVec {
    fn default() -> Self {
        Self {
            species: HashSet::new(),
            organelles: HashSet::new(),
            tax_strings: HashSet::new(),
            functions: HashSet::new(),
            genes: HashSet::new(),
            gene_synonyms: HashSet::new(),
            common_name: HashSet::new(),
            notes: HashSet::new(),
            locus_tags: HashSet::new(),
            standard_names: HashSet::new(),
            products: HashSet::new(),
        }
    }
}

impl From<RawAccession> for CrossReference {
    fn from(raw: RawAccession) -> Self {
        Self {
            name: raw.database,
            external_id: raw.external_id,
            optional_id: raw.optional_id,
            accession: raw.accession,
            non_coding_id: raw.non_coding_id,
            parent_accession: raw.parent_accession,
        }
    }
}

impl FromIterator<RawAccession> for AccessionVec {
    fn from_iter<I: IntoIterator<Item = RawAccession>>(iter: I) -> Self {
        let mut a = AccessionVec::default();

        for i in iter {
            a.species.extend(i.species.into_iter().filter(|s| !s.is_empty()));
            a.tax_strings.extend(i.tax_strings.into_iter().filter(|t| !t.is_empty()));
            a.organelles.extend(i.organelles.clone().filter(|t| !t.is_empty()));
            a.functions.extend(i.functions.into_iter().filter(|t| !t.is_empty()));
            a.genes.extend(i.genes.into_iter().filter(|t| !t.is_empty()));
            a.common_name.extend(i.common_name.into_iter().filter(|t| !t.is_empty()));
            a.notes.extend(i.notes.into_iter().filter(|t| !t.is_empty()));
            a.locus_tags.extend(i.locus_tags.into_iter().filter(|t| !t.is_empty()));
            a.standard_names.extend(i.standard_names.into_iter().filter(|t| !t.is_empty()));
            a.products.extend(i.products.into_iter().filter(|t| !t.is_empty()));

            for synonyms in i.gene_synonyms.into_iter() {
                if synonyms.contains(";") {
                    a.gene_synonyms
                        .extend(synonyms.split(";").map(|p| p.trim()).map(str::to_string))
                } else if synonyms.contains(",") {
                    a.gene_synonyms
                        .extend(synonyms.split(",").map(|p| p.trim()).map(str::to_string))
                } else {
                    a.gene_synonyms.insert(synonyms);
                }
            }
        }

        a
    }
}

impl FromIterator<RawAccession> for ReferenceVec {
    fn from_iter<I: IntoIterator<Item = RawAccession>>(iter: I) -> Self {
        let mut value = ReferenceVec::default();

        for i in iter {
            if i.authors.is_some() {
                let authors = i.authors.unwrap();
                let authors = authors.split(", ").filter(|a| !a.is_empty()).map(|s| s.to_string());
                value.authors.extend(authors);
            }

            value.journals.extend(i.journal.into_iter());
            value.pub_titles.extend(i.pub_title.into_iter().filter(|t| !t.is_empty()));
            value.pub_ids.extend(i.pub_id.into_iter());
            value.pubmed_ids.extend(i.pubmed_id.into_iter().filter(|t| !t.is_empty()));
            value.dois.extend(i.doi.into_iter().filter(|t| !t.is_empty()));
        }

        value
    }
}
<|endoftext|>


<commit_before>#![feature(proc_macro_hygiene)]

use std::io::{self, Write};

fn main() {
    let mut args = std::env::args();
    args.next().unwrap();

    let opmap = match args.next().expect("Architecture name").as_str() {
        "x64" => dynasm::dynasm_opmap!(x64),
        "aarch64" => dynasm::dynasm_opmap!(aarch64),
        x => panic!("Unknown opmap format '{}'", x)
    };

    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    stdout.write_all(opmap.as_bytes()).unwrap();
}
<commit_msg>Remove unnecessary feature from instruction reference documentation generation code<commit_after>use std::io::{self, Write};

fn main() {
    let mut args = std::env::args();
    args.next().unwrap();

    let opmap = match args.next().expect("Architecture name").as_str() {
        "x64" => dynasm::dynasm_opmap!(x64),
        "aarch64" => dynasm::dynasm_opmap!(aarch64),
        x => panic!("Unknown opmap format '{}'", x)
    };

    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    stdout.write_all(opmap.as_bytes()).unwrap();
}
<|endoftext|>