<commit_before>use svm::cell::SVMCell;
use svm::slist::List;

use self::ExprNode::*;
use self::NumNode::*;

static INDENT: &'static str = "\t";

/// Trait for AST nodes.
pub trait ASTNode {
    /// Compile this node to a list of SVM expressions
    fn compile(self)                    -> Result<SVMCell, &'static str>;

    /// Pretty-print this node
    fn prettyprint(&self)               -> String { self.print_level(0usize) }

    /// Pretty-print this node at the desired indent level
    fn print_level(&self, level: usize) -> String;
}

/// Expression
///
/// All Seax Scheme expressions are one of the following
///  + Nested S-Expressions
///  + Identifiers
///  + Lists
///  + Numbers
///     - signed int
///     - unsigned int
///     - floating-point
///  + Characters
///  + Strings
///  TODO: implement the entire Scheme 'numeric tower'
///  TODO: macros should happen
///  TODO: figure out quasiquote somehow.
#[derive(Clone, PartialEq,Debug)]
pub enum ExprNode {
    Root(RootNode),
    SExpr(SExprNode),
    Name(NameNode),
    ListConst(ListNode),
    NumConst(NumNode),
    BoolConst(BoolNode),
    StringConst(StringNode),
    CharConst(CharNode),
}

impl ASTNode for ExprNode {
    fn compile(self) -> Result<SVMCell, &'static str> {
        match self {
            Root(node)          => node.compile(),
            SExpr(node)         => node.compile(),
            Name(node)          => node.compile(),
            ListConst(node)     => node.compile(),
            NumConst(node)      => node.compile(),
            BoolConst(node)     => node.compile(),
            CharConst(node)     => node.compile(),
            StringConst(node)   => node.compile()
        }
    }

    fn print_level(&self, level: usize) -> String {
        match *self {
            Root(ref node)          => node.print_level(level),
            SExpr(ref node)         => node.print_level(level),
            Name(ref node)          => node.print_level(level),
            ListConst(ref node)     => node.print_level(level),
            NumConst(ref node)      => node.print_level(level),
            BoolConst(ref node)     => node.print_level(level),
            CharConst(ref node)     => node.print_level(level),
            StringConst(ref node)   => node.print_level(level)
        }
    }
}

#[derive(Clone, PartialEq,Debug)]
pub enum NumNode {
    IntConst(IntNode),
    UIntConst(UIntNode),
    FloatConst(FloatNode)
}

/// AST node for the root of a program's AST
#[derive(Clone, PartialEq,Debug)]
pub struct RootNode { pub exprs: Vec<ExprNode> }

impl ASTNode for RootNode {
    fn compile(self) -> Result<SVMCell, &'static str> {
        Err("UNINPLEMENTED")
    }
    fn print_level(&self, level: usize) -> String {
        self.exprs
            .iter()
            .fold(
                String::new(),
                |mut s, i| {
                    s.push_str(i.print_level(level + 1).as_slice());
                    s
                })
    }

}

/// AST node for an S-expression.
///
/// This includes function application, assignment,
/// function definition, et cetera...Scheme is not a complexl anguage.
#[derive(Clone, PartialEq,Debug)]
pub struct SExprNode {
    pub operator: NameNode,
    pub operands: Vec<ExprNode>,
}

impl ASTNode for SExprNode {

    fn compile(self) -> Result<SVMCell, &'static str> {
        Err("UNINPLEMENTED")
    }

    fn print_level(&self, level: usize) -> String {
        let mut tab = String::new();
        for _ in 0 .. level { tab.push_str(INDENT); };

        let mut result = String::new();
        result.push_str("S-Expression:\n");
        tab.push_str(INDENT);

        // op
        result.push_str(tab.as_slice());
        result.push_str("Operator:\n");
        result.push_str(self.operator.print_level(level + 1).as_slice());
        result.push('\n');

        for operand in self.operands.iter() {
            result.push_str(tab.as_slice());
            result.push_str("Operand: \n");
            result.push_str(operand.print_level(level + 1).as_slice());
            result.push('\n');
        };
        result
    }

}

/// AST node for a list literal
#[derive(Clone, PartialEq,Debug)]
pub struct ListNode { pub elements: Vec<ExprNode> }

impl ASTNode for ListNode {
    fn compile(self) -> Result<SVMCell, &'static str> {
        Err("UNINPLEMENTED")
    }
    fn print_level(&self, level: usize) -> String {
        let mut tab = String::new();
        for _ in 0 .. level {tab.push_str(INDENT); };

        let mut result = String::new();
        result.push_str("List:\n");
        tab.push_str(INDENT);

        for elem in self.elements.iter() {
            result.push_str(tab.as_slice());
            result.push_str(elem.print_level(level + 1).as_slice());
            result.push('\n');
        };
        result
    }

}

/// AST node for an identifier
#[derive(Clone, PartialEq,Debug)]
pub struct NameNode { pub name: String }

impl ASTNode for NameNode {
    fn compile(self) -> Result<SVMCell, &'static str> {
        Err("UNINPLEMENTED")
    }
    fn print_level(&self, level: usize) -> String {
        let mut tab = String::new();
        for _ in 0 .. level {tab.push_str(INDENT)};

        let mut result = String::new();
        result.push_str(tab.as_slice());
        result.push_str("Name: ");
        result.push_str(self.name.as_slice());
        result.push_str("\n");

        result
    }

}

/// AST node for an integer constant
#[derive(Clone, PartialEq,Debug)]
pub struct IntNode { pub value: isize }

impl ASTNode for NumNode {
    fn compile(self) -> Result<SVMCell, &'static str> {
        Err("UNINPLEMENTED")
    }
    fn print_level(&self, level: usize) -> String {
        let mut tab = String::new();
        for _ in 0 .. level {tab.push_str(INDENT);};

        let mut result = String::new();

        result.push_str(tab.as_slice());
        result.push_str("Number: ");

        match *self {
            NumNode::UIntConst(ref node) => {
                result.push_str(format!("{}u", node.value).as_slice());
                result.push_str("\n");
            },
            NumNode::IntConst(ref node) => {
                result.push_str(format!("{}", node.value).as_slice());
                result.push_str("\n");
            },
            NumNode::FloatConst(ref node) => {
                result.push_str(format!("{}f", node.value).as_slice());
                result.push_str("\n");
            }
        }
        result
    }
}

/// AST node for an unsigned integer constant
#[derive(Clone, PartialEq,Debug)]
pub struct UIntNode { pub value: usize }

/// AST node for a floating-point constant
#[derive(Clone, PartialEq,Debug)]
pub struct FloatNode { pub value: f64 }

/// AST node for a boolean constant
#[derive(Clone, PartialEq,Debug)]
pub struct BoolNode { pub value: bool }

impl ASTNode for BoolNode {

    fn compile(self) -> Result<SVMCell, &'static str> {
        Err("UNINPLEMENTED")
    }

    fn print_level(&self, level: usize) -> String {
        let mut tab = String::new();
        for _ in 0 .. level {tab.push_str(INDENT);};

        let mut result = String::new();

        result.push_str(tab.as_slice());
        result.push_str("Boolean: ");
        result.push_str(format!("{}", self.value).as_slice());
        result.push_str("\n");
        result
    }
}

/// AST node for a character constant
#[derive(Clone, PartialEq,Debug)]
pub struct CharNode { pub value: char }

impl ASTNode for CharNode {
    fn compile(self) -> Result<SVMCell, &'static str> {
        Err("UNINPLEMENTED")
    }
    fn print_level(&self, level: usize) -> String {
        let mut tab = String::new();
        for _ in 0 .. level {tab.push_str(INDENT);};

        let mut result = String::new();

        result.push_str("Character: \'");
        result.push(self.value);
        result.push_str("\'\n");
        result
    }
}

/// AST node for a  string constant
#[derive(Clone, PartialEq,Debug)]
pub struct StringNode { pub value: String }

impl ASTNode for StringNode {
    fn compile(self) -> Result<SVMCell, &'static str> {
        Err("UNINPLEMENTED")
    }
    fn print_level(&self, level: usize) -> String {
        let mut tab = String::new();
        for _ in 0 .. level {tab.push_str(INDENT);};

        let mut result = String::new();

        result.push_str("String: \"");
        result.push_str(self.value.as_slice());
        result.push_str("\"\n");
        result
    }
}

<commit_msg>Remove unused import<commit_after>use svm::cell::SVMCell;

use self::ExprNode::*;
use self::NumNode::*;

static INDENT: &'static str = "\t";

/// Trait for AST nodes.
pub trait ASTNode {
    /// Compile this node to a list of SVM expressions
    fn compile(self)                    -> Result<SVMCell, &'static str>;

    /// Pretty-print this node
    fn prettyprint(&self)               -> String { self.print_level(0usize) }

    /// Pretty-print this node at the desired indent level
    fn print_level(&self, level: usize) -> String;
}

/// Expression
///
/// All Seax Scheme expressions are one of the following
///  + Nested S-Expressions
///  + Identifiers
///  + Lists
///  + Numbers
///     - signed int
///     - unsigned int
///     - floating-point
///  + Characters
///  + Strings
///  TODO: implement the entire Scheme 'numeric tower'
///  TODO: macros should happen
///  TODO: figure out quasiquote somehow.
#[derive(Clone, PartialEq,Debug)]
pub enum ExprNode {
    Root(RootNode),
    SExpr(SExprNode),
    Name(NameNode),
    ListConst(ListNode),
    NumConst(NumNode),
    BoolConst(BoolNode),
    StringConst(StringNode),
    CharConst(CharNode),
}

impl ASTNode for ExprNode {
    fn compile(self) -> Result<SVMCell, &'static str> {
        match self {
            Root(node)          => node.compile(),
            SExpr(node)         => node.compile(),
            Name(node)          => node.compile(),
            ListConst(node)     => node.compile(),
            NumConst(node)      => node.compile(),
            BoolConst(node)     => node.compile(),
            CharConst(node)     => node.compile(),
            StringConst(node)   => node.compile()
        }
    }

    fn print_level(&self, level: usize) -> String {
        match *self {
            Root(ref node)          => node.print_level(level),
            SExpr(ref node)         => node.print_level(level),
            Name(ref node)          => node.print_level(level),
            ListConst(ref node)     => node.print_level(level),
            NumConst(ref node)      => node.print_level(level),
            BoolConst(ref node)     => node.print_level(level),
            CharConst(ref node)     => node.print_level(level),
            StringConst(ref node)   => node.print_level(level)
        }
    }
}

#[derive(Clone, PartialEq,Debug)]
pub enum NumNode {
    IntConst(IntNode),
    UIntConst(UIntNode),
    FloatConst(FloatNode)
}

/// AST node for the root of a program's AST
#[derive(Clone, PartialEq,Debug)]
pub struct RootNode { pub exprs: Vec<ExprNode> }

impl ASTNode for RootNode {
    fn compile(self) -> Result<SVMCell, &'static str> {
        Err("UNINPLEMENTED")
    }
    fn print_level(&self, level: usize) -> String {
        self.exprs
            .iter()
            .fold(
                String::new(),
                |mut s, i| {
                    s.push_str(i.print_level(level + 1).as_slice());
                    s
                })
    }

}

/// AST node for an S-expression.
///
/// This includes function application, assignment,
/// function definition, et cetera...Scheme is not a complexl anguage.
#[derive(Clone, PartialEq,Debug)]
pub struct SExprNode {
    pub operator: NameNode,
    pub operands: Vec<ExprNode>,
}

impl ASTNode for SExprNode {

    fn compile(self) -> Result<SVMCell, &'static str> {
        Err("UNINPLEMENTED")
    }

    fn print_level(&self, level: usize) -> String {
        let mut tab = String::new();
        for _ in 0 .. level { tab.push_str(INDENT); };

        let mut result = String::new();
        result.push_str("S-Expression:\n");
        tab.push_str(INDENT);

        // op
        result.push_str(tab.as_slice());
        result.push_str("Operator:\n");
        result.push_str(self.operator.print_level(level + 1).as_slice());
        result.push('\n');

        for operand in self.operands.iter() {
            result.push_str(tab.as_slice());
            result.push_str("Operand: \n");
            result.push_str(operand.print_level(level + 1).as_slice());
            result.push('\n');
        };
        result
    }

}

/// AST node for a list literal
#[derive(Clone, PartialEq,Debug)]
pub struct ListNode { pub elements: Vec<ExprNode> }

impl ASTNode for ListNode {
    fn compile(self) -> Result<SVMCell, &'static str> {
        Err("UNINPLEMENTED")
    }
    fn print_level(&self, level: usize) -> String {
        let mut tab = String::new();
        for _ in 0 .. level {tab.push_str(INDENT); };

        let mut result = String::new();
        result.push_str("List:\n");
        tab.push_str(INDENT);

        for elem in self.elements.iter() {
            result.push_str(tab.as_slice());
            result.push_str(elem.print_level(level + 1).as_slice());
            result.push('\n');
        };
        result
    }

}

/// AST node for an identifier
#[derive(Clone, PartialEq,Debug)]
pub struct NameNode { pub name: String }

impl ASTNode for NameNode {
    fn compile(self) -> Result<SVMCell, &'static str> {
        Err("UNINPLEMENTED")
    }
    fn print_level(&self, level: usize) -> String {
        let mut tab = String::new();
        for _ in 0 .. level {tab.push_str(INDENT)};

        let mut result = String::new();
        result.push_str(tab.as_slice());
        result.push_str("Name: ");
        result.push_str(self.name.as_slice());
        result.push_str("\n");

        result
    }

}

/// AST node for an integer constant
#[derive(Clone, PartialEq,Debug)]
pub struct IntNode { pub value: isize }

impl ASTNode for NumNode {
    fn compile(self) -> Result<SVMCell, &'static str> {
        Err("UNINPLEMENTED")
    }
    fn print_level(&self, level: usize) -> String {
        let mut tab = String::new();
        for _ in 0 .. level {tab.push_str(INDENT);};

        let mut result = String::new();

        result.push_str(tab.as_slice());
        result.push_str("Number: ");

        match *self {
            NumNode::UIntConst(ref node) => {
                result.push_str(format!("{}u", node.value).as_slice());
                result.push_str("\n");
            },
            NumNode::IntConst(ref node) => {
                result.push_str(format!("{}", node.value).as_slice());
                result.push_str("\n");
            },
            NumNode::FloatConst(ref node) => {
                result.push_str(format!("{}f", node.value).as_slice());
                result.push_str("\n");
            }
        }
        result
    }
}

/// AST node for an unsigned integer constant
#[derive(Clone, PartialEq,Debug)]
pub struct UIntNode { pub value: usize }

/// AST node for a floating-point constant
#[derive(Clone, PartialEq,Debug)]
pub struct FloatNode { pub value: f64 }

/// AST node for a boolean constant
#[derive(Clone, PartialEq,Debug)]
pub struct BoolNode { pub value: bool }

impl ASTNode for BoolNode {

    fn compile(self) -> Result<SVMCell, &'static str> {
        Err("UNINPLEMENTED")
    }

    fn print_level(&self, level: usize) -> String {
        let mut tab = String::new();
        for _ in 0 .. level {tab.push_str(INDENT);};

        let mut result = String::new();

        result.push_str(tab.as_slice());
        result.push_str("Boolean: ");
        result.push_str(format!("{}", self.value).as_slice());
        result.push_str("\n");
        result
    }
}

/// AST node for a character constant
#[derive(Clone, PartialEq,Debug)]
pub struct CharNode { pub value: char }

impl ASTNode for CharNode {
    fn compile(self) -> Result<SVMCell, &'static str> {
        Err("UNINPLEMENTED")
    }
    fn print_level(&self, level: usize) -> String {
        let mut tab = String::new();
        for _ in 0 .. level {tab.push_str(INDENT);};

        let mut result = String::new();

        result.push_str("Character: \'");
        result.push(self.value);
        result.push_str("\'\n");
        result
    }
}

/// AST node for a  string constant
#[derive(Clone, PartialEq,Debug)]
pub struct StringNode { pub value: String }

impl ASTNode for StringNode {
    fn compile(self) -> Result<SVMCell, &'static str> {
        Err("UNINPLEMENTED")
    }
    fn print_level(&self, level: usize) -> String {
        let mut tab = String::new();
        for _ in 0 .. level {tab.push_str(INDENT);};

        let mut result = String::new();

        result.push_str("String: \"");
        result.push_str(self.value.as_slice());
        result.push_str("\"\n");
        result
    }
}

<|endoftext|>


<commit_before>use sozu_command::proxy::{LoadBalancingAlgorithms, TlsVersion};
use std::net::SocketAddr;

#[derive(StructOpt, PartialEq, Debug)]
pub struct App {
  #[structopt(short="c", long = "config", help = "Sets a custom config file")]
  pub config: Option<String>,
  #[structopt(short="t", long = "timeout", help = "Sets a custom timeout for commands (in milliseconds). 0 disables the timeout")]
  pub timeout: Option<u64>,
  #[structopt(subcommand)]
  pub cmd: SubCmd,
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum SubCmd {
  #[structopt(name = "shutdown", about = "shuts down the proxy")]
  Shutdown {
    #[structopt(long = "hard", help = "do not wait for connections to finish")]
    hard: bool,
    #[structopt(short = "w", long = "worker", help = "shuts down the worker with this id")]
    worker: Option<u32>,
  },
  #[structopt(name = "upgrade", about = "upgrade the proxy")]
  Upgrade {
    #[structopt(short = "w", long = "worker", help = "Upgrade the worker with this id")]
    worker: Option<u32>,
  },
  #[structopt(name = "status", about = "gets information on the running workers")]
  Status {
    #[structopt(short = "j", long = "json", help = "Print the command result in JSON format")]
    json: bool
  },
  #[structopt(name = "metrics", about = "gets statistics on the main process and its workers")]
  Metrics {
    #[structopt(short = "j", long = "json", help = "Print the command result in JSON format")]
    json: bool
  },
  #[structopt(name = "logging", about = "change logging level")]
  Logging {
    #[structopt(short = "l", long = "level", help = "change logging level")]
    level: String
  },
  #[structopt(name = "state", about = "state management")]
  State {
    #[structopt(subcommand)]
    cmd: StateCmd,
  },
  #[structopt(name = "reload", about = "Reloads routing configuration (applications, frontends and backends)")]
  Reload{
    #[structopt(short = "f", long = "file", help = "use a different configuration file from the current one")]
    file: Option<String>,
    #[structopt(short = "j", long = "json", help = "Print the command result in JSON format")]
    json: bool
  },
  #[structopt(name = "application", about = "application management")]
  Application {
    #[structopt(subcommand)]
    cmd: ApplicationCmd,
  },
  #[structopt(name = "backend", about = "backend management")]
  Backend {
    #[structopt(subcommand)]
    cmd: BackendCmd,
  },
  #[structopt(name = "frontend", about = "frontend management")]
  Frontend {
    #[structopt(subcommand)]
    cmd: FrontendCmd,
  },
  #[structopt(name  = "listener", about = "listener management")]
  Listener {
    #[structopt(subcommand)]
    cmd: ListenerCmd
  },
  #[structopt(name = "certificate", about = "certificate management")]
  Certificate {
    #[structopt(subcommand)]
    cmd: CertificateCmd,
  },
  #[structopt(name = "query", about = "configuration state verification")]
  Query {
    #[structopt(short = "j", long = "json", help = "Print the command result in JSON format")]
    json: bool,
    #[structopt(subcommand)]
    cmd: QueryCmd,
  },
  #[structopt(name = "config", about = "configuration file management")]
  Config {
    #[structopt(subcommand)]
    cmd: ConfigCmd
  },
  #[structopt(name = "events", about = "receive sozu events")]
  Events
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum StateCmd {
  #[structopt(name = "save", about = "Save state to that file")]
  Save {
    #[structopt(short = "f", long = "file")]
    file: String,
  },
  #[structopt(name = "load", about = "Load state from that file")]
  Load {
    #[structopt(short = "f", long = "file")]
    file: String,
  },
  #[structopt(name = "dump", about = "Dump current state to STDOUT")]
  Dump {
    #[structopt(short = "j", long = "json", help = "Print the command result in JSON format")]
    json: bool
  },
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum ApplicationCmd {
  #[structopt(name = "remove", about = "Remove an application")]
  Remove {
    #[structopt(short = "i", long = "id")]
    id: String,
  },
  #[structopt(name = "add", about = "Add an application")]
  Add{
    #[structopt(short = "i", long = "id")]
    id: String,
    #[structopt(short = "s", long = "sticky-session")]
    sticky_session: bool,
    #[structopt(short = "h", long = "https-redirect")]
    https_redirect: bool,
    #[structopt(long = "send-proxy", help = "Enforces use of the PROXY protocol version 2 over any connection established to this server.")]
    send_proxy: bool,
    #[structopt(long = "expect-proxy", help = "Configures the client-facing connection to receive a PROXY protocol header version 2")]
    expect_proxy: bool,
    #[structopt(long = "load-balancing-policy", help = "Configures the load balancing policy. Possible values are 'roundrobin', 'random' or 'leastconnections'")]
    load_balancing_policy: LoadBalancingAlgorithms,
  },
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum BackendCmd {
  #[structopt(name = "remove", about = "Remove a backend")]
  Remove {
    #[structopt(short = "i", long = "id")]
    id: String,
    #[structopt(long = "backend-id")]
    backend_id: String,
    #[structopt(short = "a", long = "address", help = "server address, format: IP:port")]
    address: SocketAddr,
  },
  #[structopt(name = "add", about = "Add a backend")]
  Add {
    #[structopt(short = "i", long = "id")]
    id: String,
    #[structopt(long = "backend-id")]
    backend_id: String,
    #[structopt(short = "a", long = "address", help = "server address, format: IP:port")]
    address: SocketAddr,
    #[structopt(short = "s", long = "sticky-id", help = "value for the sticky session cookie")]
    sticky_id: Option<String>,
    #[structopt(short = "b", long = "backup", help = "set backend as a backup backend")]
    backup: Option<bool>,
  },
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum FrontendCmd {
  #[structopt(name = "http", about = "HTTP frontend management")]
  Http {
    #[structopt(subcommand)]
    cmd: HttpFrontendCmd,
  },
  #[structopt(name = "https", about = "HTTPS frontend management")]
  Https {
    #[structopt(subcommand)]
    cmd: HttpFrontendCmd,
  },
  #[structopt(name = "tcp", about = "TCP frontend management")]
  Tcp {
    #[structopt(subcommand)]
    cmd: TcpFrontendCmd,
  },
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum HttpFrontendCmd {
  #[structopt(name = "add")]
  Add {
    #[structopt(short = "a", long = "address", help = "frontend address, format: IP:port")]
    address: SocketAddr,
    #[structopt(short = "i", long = "id", help = "app id of the frontend")]
    id: String,
    #[structopt(short = "host", long = "hostname")]
    hostname: String,
    #[structopt(short = "p", long = "path", help="URL prefix of the frontend")]
    path_begin: Option<String>,
  },
  #[structopt(name = "remove")]
  Remove {
    #[structopt(short = "a", long = "address", help = "frontend address, format: IP:port")]
    address: SocketAddr,
    #[structopt(short = "i", long = "id", help = "app id of the frontend")]
    id: String,
    #[structopt(short = "host", long = "hostname")]
    hostname: String,
    #[structopt(short = "p", long = "path", help="URL prefix of the frontend")]
    path_begin: Option<String>,
  },
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum TcpFrontendCmd {
  #[structopt(name = "add")]
  Add {
    #[structopt(short = "i", long = "id", help = "app id of the frontend")]
    id: String,
    #[structopt(short = "a", long = "address", help = "frontend address, format: IP:port")]
    address: SocketAddr,
  },
  #[structopt(name = "remove")]
  Remove {
    #[structopt(short = "i", long = "id", help = "app id of the frontend")]
    id: String,
    #[structopt(short = "a", long = "address", help = "frontend address, format: IP:port")]
    address: SocketAddr,
  },
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum ListenerCmd {
  #[structopt(name = "http", about = "HTTP listener management")]
  Http {
    #[structopt(subcommand)]
    cmd: HttpListenerCmd,
  },
  #[structopt(name = "https", about = "HTTPS listener management")]
  Https {
    #[structopt(subcommand)]
    cmd: HttpsListenerCmd,
  },
  #[structopt(name = "tcp", about = "TCP listener management")]
  Tcp {
    #[structopt(subcommand)]
    cmd: TcpListenerCmd,
  },
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum HttpListenerCmd {
  #[structopt(name = "add")]
  Add {
    #[structopt(short = "a")]
    address: SocketAddr,
    #[structopt(long = "public-address", help = "a different IP than the one the socket sees, for logs and forwarded headers")]
    public_address: Option<SocketAddr>,
    #[structopt(long = "answer-404", help = "path to file of the 404 answer sent to the client when a frontend is not found")]
    answer_404: Option<String>,
    #[structopt(long = "answer-503", help = "path to file of the 503 answer sent to the client when an application has no backends available")]
    answer_503: Option<String>,
    #[structopt(long = "expect-proxy", help = "Configures the client socket to receive a PROXY protocol header")]
    expect_proxy: bool,
    #[structopt(long = "sticky-name", help = "sticky session cookie name")]
    sticky_name: Option<String>
  },
  #[structopt(name = "remove")]
  Remove {
    #[structopt(short = "a", long = "address", help = "listener address, format: IP:port")]
    address: SocketAddr,
  },
  #[structopt(name = "activate")]
  Activate {
    #[structopt(short = "a", long = "address", help = "listener address, format: IP:port")]
    address: SocketAddr
  },
  #[structopt(name = "deactivate")]
  Deactivate {
    #[structopt(short = "a", long = "address", help = "listener address, format: IP:port")]
    address: SocketAddr
  }
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum HttpsListenerCmd {
  #[structopt(name = "add")]
  Add {
    #[structopt(short = "a")]
    address: SocketAddr,
    #[structopt(long = "public-address", help = "a different IP than the one the socket sees, for logs and forwarded headers")]
    public_address: Option<SocketAddr>,
    #[structopt(long = "answer-404", help = "path to file of the 404 answer sent to the client when a frontend is not found")]
    answer_404: Option<String>,
    #[structopt(long = "answer-503", help = "path to file of the 503 answer sent to the client when an application has no backends available")]
    answer_503: Option<String>,
    #[structopt(long = "tls-versions", help = "list of TLS versions to use")]
    tls_versions: Vec<TlsVersion>,
    #[structopt(long = "tls-ciphers-list", help = "list of OpenSSL TLS ciphers to use")]
    cipher_list: Option<String>,
    #[structopt(long = "rustls-cipher-list", help = "list of RustTLS ciphers to use")]
    rustls_cipher_list: Vec<String>,
    #[structopt(long = "expect-proxy", help = "Configures the client socket to receive a PROXY protocol header")]
    expect_proxy: bool,
    #[structopt(long = "sticky-name", help = "sticky session cookie name")]
    sticky_name: Option<String>
  },
  #[structopt(name = "remove")]
  Remove {
    #[structopt(short = "a", long = "address", help = "listener address, format: IP:port")]
    address: SocketAddr,
  },
  #[structopt(name = "activate")]
  Activate {
    #[structopt(short = "a", long = "address", help = "listener address, format: IP:port")]
    address: SocketAddr
  },
  #[structopt(name = "deactivate")]
  Deactivate {
    #[structopt(short = "a", long = "address", help = "listener address, format: IP:port")]
    address: SocketAddr
  }
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum TcpListenerCmd {
  #[structopt(name = "add")]
  Add {
    #[structopt(short = "a", long = "address", help = "listener address, format: IP:port")]
    address: SocketAddr,
    #[structopt(long = "public-address", help = "a different IP than the one the socket sees, for logs and forwarded headers")]
    public_address: Option<SocketAddr>,
    #[structopt(long = "expect-proxy", help = "Configures the client socket to receive a PROXY protocol header")]
    expect_proxy: bool
  },
  #[structopt(name = "remove")]
  Remove {
    #[structopt(short = "a", long = "address", help = "listener address, format: IP:port")]
    address: SocketAddr,
  },
  #[structopt(name = "activate")]
  Activate {
    #[structopt(short = "a", long = "address", help = "listener address, format: IP:port")]
    address: SocketAddr
  },
  #[structopt(name = "deactivate")]
  Deactivate {
    #[structopt(short = "a", long = "address", help = "listener address, format: IP:port")]
    address: SocketAddr
  }
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum CertificateCmd {
  #[structopt(name = "add", about = "Add a certificate")]
  Add {
    #[structopt(short = "a", long = "address", help = "listener address, format: IP:port")]
    address: SocketAddr,
    #[structopt(long = "certificate", help = "path to the certificate")]
    certificate: String,
    #[structopt(long = "certificate-chain", help = "path to the certificate chain")]
    chain: String,
    #[structopt(long = "key", help = "path to the key")]
    key: String,
    #[structopt(long = "tls-versions", help = "accepted TLS versions for this certificate",
                parse(try_from_str = parse_tls_versions))]
    tls_versions: Vec<TlsVersion>,
    #[structopt(long = "names", use_delimiter = true, help="list of comma separated domain names (wildcard allowed)")]
    names : Vec<String>,
  },
  #[structopt(name = "remove", about = "Remove a certificate")]
  Remove {
    #[structopt(short = "a", long = "address", help = "listener address, format: IP:port")]
    address: SocketAddr,
    #[structopt(short = "cert", long = "certificate", help = "path to the certificate")]
    certificate: Option<String>,
    #[structopt(short = "f", long = "fingerprint", help = "certificate fingerprint")]
    fingerprint: Option<String>,
  },
  #[structopt(name = "replace", about = "Replace an existing certificate")]
  Replace {
    #[structopt(short = "a", long = "address", help = "listener address, format: IP:port")]
    address: SocketAddr,
    #[structopt(long = "new-certificate", help = "path to the new certificate")]
    certificate: String,
    #[structopt(long = "new-certificate-chain", help = "path to the new certificate chain")]
    chain: String,
    #[structopt(long = "new-key", help = "path to the new key")]
    key: String,
    #[structopt(short = "old-cert", long = "old-certificate", help = "path to the old certificate")]
    old_certificate: Option<String>,
    #[structopt(short = "f", long = "fingerprint", help = "old certificate fingerprint")]
    old_fingerprint: Option<String>,
    #[structopt(long = "tls-versions", help = "accepted TLS versions for this certificate",
                parse(try_from_str = parse_tls_versions))]
    tls_versions: Vec<TlsVersion>,
  }
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum QueryCmd {
  #[structopt(name = "applications", about = "Query applications matching a specific filter")]
  Applications {
    #[structopt(short = "i", long="id", help="application identifier")]
    id: Option<String>,
    #[structopt(short = "d", long="domain", help="application domain name")]
    domain: Option<String>
  },

  #[structopt(name = "certificates", about = "Query certificates matching a specific filter")]
  Certificates {
    #[structopt(short = "f", long="fingerprint", help="certificate fingerprint")]
    fingerprint: Option<String>,
    #[structopt(short = "d", long="domain", help="domain name")]
    domain: Option<String>
  }
}

#[derive(StructOpt, PartialEq, Debug)]
pub enum ConfigCmd {
  #[structopt(name = "check", about = "check configuration file syntax and exit")]
  Check {}
}

fn parse_tls_versions(i: &str) -> Result<TlsVersion, String> {
    match i {
        "TLSv1" => Ok(TlsVersion::TLSv1_0),
        "TLSv1.1" => Ok(TlsVersion::TLSv1_1),
        "TLSv1.2" => Ok(TlsVersion::TLSv1_2),
        "TLSv1.3" => Ok(TlsVersion::TLSv1_2),
        s => return Err(format!("unrecognized TLS version: {}", s)),
    }
}

<commit_msg>unused file<commit_after><|endoftext|>


<commit_before>pub mod segment;

use std::path::PathBuf;
use std::fs::File;
use std::path::Path;
use std::fs;

use super::{Storage, StorageError, StorageResult};
use super::{Page, PAGE_SIZE, PageError};
use super::{Row, RowBuilder};

pub use self::segment::Segment;

pub struct Disk {
    segment_size: usize, // bytes
    pages_per_segment: usize,
    directory: PathBuf,
    first_segment: u64,
    segments: Vec<Segment>,
    current_page: Page,
    current_segment: Segment,
    segment_sequence_id: u64,
}

impl Disk {

    // dir is the directory of the segments
    pub fn new(segment_size_in_mb: usize, dir: PathBuf) -> StorageResult<Disk> {
        // create the data directory for this disk storage
        fs::create_dir(&dir).expect("Could not create disk storage");

        let segment_size = segment_size_in_mb * 1024 * 1024;
        let pages_per_segment = segment_size / PAGE_SIZE;

        let segment = Disk::open_segment(&dir, 0).expect("Could not open new segment");

        Ok(Disk{segment_size: segment_size,
            directory: dir,
            pages_per_segment: pages_per_segment,
            segments: Vec::new(),
            first_segment: 0,
            current_page: Page::new(),
            current_segment: segment,
            segment_sequence_id: 0})
    }

    pub fn open_segment(dir: &PathBuf, id: u64) -> StorageResult<Segment> {
        let name = format!("seg{}.segment", id);
        let seg_path = dir.as_path().join(name);
        info!("Creating new segment at {:?}", seg_path);
        let segment = Segment::new(&seg_path).expect("Disk Storage: Could not create segment");
        Ok(segment)

    }

    // close the current segment and open a new one
    pub fn flush(&mut self) -> StorageResult<()> {
        info!("Flushing segment {}", self.segment_sequence_id);
        info!("Current segment: {:?}", self.current_segment);
        self.segment_sequence_id += 1;
//        self.current_segment.close();
        let segment = Disk::open_segment(&self.directory, self.segment_sequence_id).expect("Expected segment");
        self.current_segment = segment;
        Ok(())
    }

}

impl Storage for Disk {

    // getting a page requires first getting the right segment
    fn get_page(&self, page: u64) -> StorageResult<Page> {
        Err(StorageError::PageNotFound)
    }
    fn write_page(&mut self, page: &Page) -> StorageResult<()> {
        // write the page to the current segment
        // check if the segment is full
        // if it's full, close and open a new one
        Ok(())
    }

}

#[cfg(test)]
mod tests {
    use super::{Disk, Page};
    use tempdir::TempDir;

    fn get_disk_storage() -> Disk {
        let dir = TempDir::new("disk_storage").expect("Need a temp dir");
        let dir2 = dir.path().join("stream");
        Disk::new(1, dir2).expect("Want that disk")
    }

    #[test]
    fn test_disk_flush() {
        let mut disk = get_disk_storage();
        disk.flush();
        disk.flush();
    }

    #[test]
    fn test_disk_writes_segments_correctly() {

    }
}<commit_msg>fixed bug with TempDir clearing directory before test is finished<commit_after>pub mod segment;

use std::path::PathBuf;
use std::fs::File;
use std::path::Path;
use std::fs;

use super::{Storage, StorageError, StorageResult};
use super::{Page, PAGE_SIZE, PageError};
use super::{Row, RowBuilder};

pub use self::segment::Segment;

pub struct Disk {
    segment_size: usize, // bytes
    pages_per_segment: usize,
    directory: PathBuf,
    first_segment: u64,
    segments: Vec<Segment>,
    current_page: Page,
    current_segment: Segment,
    segment_sequence_id: u64,
}

impl Disk {

    // dir is the directory of the segments
    pub fn new(segment_size_in_mb: usize, dir: PathBuf) -> StorageResult<Disk> {
        // create the data directory for this disk storage
        fs::create_dir(&dir).expect("Could not create disk storage");

        let segment_size = segment_size_in_mb * 1024 * 1024;
        let pages_per_segment = segment_size / PAGE_SIZE;

        let segment = Disk::open_segment(&dir, 0).expect("Could not open new segment");

        Ok(Disk{segment_size: segment_size,
            directory: dir,
            pages_per_segment: pages_per_segment,
            segments: Vec::new(),
            first_segment: 0,
            current_page: Page::new(),
            current_segment: segment,
            segment_sequence_id: 0})
    }

    pub fn open_segment(dir: &PathBuf, id: u64) -> StorageResult<Segment> {
        let name = format!("seg{}.segment", id);
        let seg_path = dir.as_path().join(name);
        info!("Creating new segment at {:?}", seg_path);
        let segment = Segment::new(&seg_path).expect("Disk Storage: Could not create segment");
        Ok(segment)

    }

    // close the current segment and open a new one
    pub fn flush(&mut self) -> StorageResult<()> {
        info!("Flushing segment {}", self.segment_sequence_id);
        info!("Current segment: {:?}", self.current_segment);
        self.segment_sequence_id += 1;
//        self.current_segment.close();
        let segment = Disk::open_segment(&self.directory, self.segment_sequence_id).expect("Expected segment");
        self.current_segment = segment;
        Ok(())
    }

}

impl Storage for Disk {

    // getting a page requires first getting the right segment
    fn get_page(&self, page: u64) -> StorageResult<Page> {
        Err(StorageError::PageNotFound)
    }
    fn write_page(&mut self, page: &Page) -> StorageResult<()> {
        // write the page to the current segment
        // check if the segment is full
        // if it's full, close and open a new one
        Ok(())
    }

}

#[cfg(test)]
mod tests {
    use super::{Disk, Page};
    use tempdir::TempDir;

    fn get_disk_storage() -> Disk {
        let mut dir = TempDir::new("disk_storage").expect("Need a temp dir").into_path();
        dir.push("stream");
        Disk::new(1, dir).expect("Want that disk")
    }

    #[test]
    fn test_disk_flush() {
        let mut disk = get_disk_storage();
        disk.flush();
        disk.flush();
    }

    #[test]
    fn test_disk_writes_segments_correctly() {

    }
}<|endoftext|>


<commit_before>use std::env;
use std::fmt::{self, Debug, Formatter};
use std::ops::Deref;
use std::path::{Path, PathBuf};

use dirs::home_dir;
use nix::NixPath;

use crate::env_name::NMK_HOME;

/// Home directory of dotfiles
#[derive(Clone)]
pub struct NmkHome(PathBuf);

impl Debug for NmkHome {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        Debug::fmt(&self.0, f)
    }
}

fn find_path_from_homedir() -> Option<PathBuf> {
    home_dir().map(|p| p.join(".nmk"))
}

fn find_path_from_env() -> Option<PathBuf> {
    env::var_os(NMK_HOME)
        .map(PathBuf::from)
        .filter(PathBuf::is_empty)
}

impl NmkHome {
    pub fn is_git(&self) -> bool {
        self.0.join(".git").exists()
    }

    /// Attempt to find correct NMK_HOME candidate
    /// - if NMK_HOME is set, canonicalize it
    /// - otherwise default to $HOME/.nmk
    ///
    /// Canonicalization is necessary because we use this value in vendored zsh which required
    /// absolute path.
    pub fn find() -> Option<Self> {
        find_path_from_env()
            .and_then(|p| p.canonicalize().ok())
            .or_else(find_path_from_homedir)
            .map(Self::from)
    }

    /// Like find but don't canonicalize (it fail if directory doesn't exist)
    pub fn find_for_install() -> Option<Self> {
        find_path_from_env()
            .or_else(find_path_from_homedir)
            .map(Self::from)
    }
}

impl From<PathBuf> for NmkHome {
    fn from(inner: PathBuf) -> Self {
        Self(inner)
    }
}

impl Deref for NmkHome {
    type Target = Path;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl AsRef<Path> for NmkHome {
    fn as_ref(&self) -> &Path {
        self.0.as_ref()
    }
}
<commit_msg>Fix wrong logic<commit_after>use std::env;
use std::fmt::{self, Debug, Formatter};
use std::ops::Deref;
use std::path::{Path, PathBuf};

use dirs::home_dir;
use nix::NixPath;

use crate::env_name::NMK_HOME;

/// Home directory of dotfiles
#[derive(Clone)]
pub struct NmkHome(PathBuf);

impl Debug for NmkHome {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        Debug::fmt(&self.0, f)
    }
}

fn find_path_from_homedir() -> Option<PathBuf> {
    home_dir().map(|p| p.join(".nmk"))
}

fn find_path_from_env() -> Option<PathBuf> {
    env::var_os(NMK_HOME)
        .map(PathBuf::from)
        .filter(|p| !p.is_empty())
}

impl NmkHome {
    pub fn is_git(&self) -> bool {
        self.0.join(".git").exists()
    }

    /// Attempt to find correct NMK_HOME candidate
    /// - if NMK_HOME is set, canonicalize it
    /// - otherwise default to $HOME/.nmk
    ///
    /// Canonicalization is necessary because we use this value in vendored zsh which required
    /// absolute path.
    pub fn find() -> Option<Self> {
        find_path_from_env()
            .and_then(|p| p.canonicalize().ok())
            .or_else(find_path_from_homedir)
            .map(Self::from)
    }

    /// Like find but don't canonicalize (it fail if directory doesn't exist)
    pub fn find_for_install() -> Option<Self> {
        find_path_from_env()
            .or_else(find_path_from_homedir)
            .map(Self::from)
    }
}

impl From<PathBuf> for NmkHome {
    fn from(inner: PathBuf) -> Self {
        Self(inner)
    }
}

impl Deref for NmkHome {
    type Target = Path;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl AsRef<Path> for NmkHome {
    fn as_ref(&self) -> &Path {
        self.0.as_ref()
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "fatal_warnings", deny(warnings))]

extern crate libc;
extern crate rand;

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serde;

mod libindy;
#[macro_use]
mod utils;
#[macro_use]
mod payment_method;
mod services;

use std::ffi::CString;

#[no_mangle]
pub extern fn nullpay_init() -> ErrorCode {
    if let Err(err) = utils::logger::LibnullpayLogger::init() {
        return err;
    }

    let payment_method_name = CString::new(payment_method::PAYMENT_METHOD_NAME).unwrap();

    libindy::payments::register_payment_method(
        payment_method_name.as_ptr(),
        payment_method::create_payment_address::handle,
        payment_method::add_request_fees::handle,
        payment_method::parse_response_with_fees::handle,
        payment_method::build_get_payment_sources_request::handle,
        payment_method::parse_get_payment_sources_response::handle,
        payment_method::build_payment_req::handle,
        payment_method::parse_payment_response::handle,
        payment_method::build_mint_req::handle,
        payment_method::build_set_txn_fees_req::handle,
        payment_method::build_get_txn_fees_req::handle,
        payment_method::parse_get_txn_fees_response::handle,
        payment_method::build_verify_payment_req::handle,
        payment_method::parse_verify_payment_response::handle,
    )
}

#[derive(Debug, PartialEq, Copy, Clone)]
#[repr(i32)]
pub enum ErrorCode
{
    Success = 0,

    // Common errors

    // Caller passed invalid value as param 1 (null, invalid json and etc..)
    CommonInvalidParam1 = 100,

    // Caller passed invalid value as param 2 (null, invalid json and etc..)
    CommonInvalidParam2 = 101,

    // Caller passed invalid value as param 3 (null, invalid json and etc..)
    CommonInvalidParam3 = 102,

    // Caller passed invalid value as param 4 (null, invalid json and etc..)
    CommonInvalidParam4 = 103,

    // Caller passed invalid value as param 5 (null, invalid json and etc..)
    CommonInvalidParam5 = 104,

    // Caller passed invalid value as param 6 (null, invalid json and etc..)
    CommonInvalidParam6 = 105,

    // Caller passed invalid value as param 7 (null, invalid json and etc..)
    CommonInvalidParam7 = 106,

    // Caller passed invalid value as param 8 (null, invalid json and etc..)
    CommonInvalidParam8 = 107,

    // Caller passed invalid value as param 9 (null, invalid json and etc..)
    CommonInvalidParam9 = 108,

    // Caller passed invalid value as param 10 (null, invalid json and etc..)
    CommonInvalidParam10 = 109,

    // Caller passed invalid value as param 11 (null, invalid json and etc..)
    CommonInvalidParam11 = 110,

    // Caller passed invalid value as param 12 (null, invalid json and etc..)
    CommonInvalidParam12 = 111,

    // Invalid library state was detected in runtime. It signals library bug
    CommonInvalidState = 112,

    // Object (json, config, key, credential and etc...) passed by library caller has invalid structure
    CommonInvalidStructure = 113,

    // IO Error
    CommonIOError = 114,

    // Caller passed invalid value as param 13 (null, invalid json and etc..)
    CommonInvalidParam13 = 115,

    // Caller passed invalid value as param 14 (null, invalid json and etc..)
    CommonInvalidParam14 = 116,

    // Wallet errors
    // Caller passed invalid wallet handle
    WalletInvalidHandle = 200,

    // Unknown type of wallet was passed on create_wallet
    WalletUnknownTypeError = 201,

    // Attempt to register already existing wallet type
    WalletTypeAlreadyRegisteredError = 202,

    // Attempt to create wallet with name used for another exists wallet
    WalletAlreadyExistsError = 203,

    // Requested entity id isn't present in wallet
    WalletNotFoundError = 204,

    // Trying to use wallet with pool that has different name
    WalletIncompatiblePoolError = 205,

    // Trying to open wallet that was opened already
    WalletAlreadyOpenedError = 206,

    // Attempt to open encrypted wallet with invalid credentials
    WalletAccessFailed = 207,

    // Input provided to wallet operations is considered not valid
    WalletInputError = 208,

    // Decoding of wallet data during input/output failed
    WalletDecodingError = 209,

    // Storage error occurred during wallet operation
    WalletStorageError = 210,

    // Error during encryption-related operations
    WalletEncryptionError = 211,

    // Requested wallet item not found
    WalletItemNotFound = 212,

    // Returned if wallet's add_record operation is used with record name that already exists
    WalletItemAlreadyExists = 213,

    // Returned if provided wallet query is invalid
    WalletQueryError = 214,

    // Ledger errors
    // Trying to open pool ledger that wasn't created before
    PoolLedgerNotCreatedError = 300,

    // Caller passed invalid pool ledger handle
    PoolLedgerInvalidPoolHandle = 301,

    // Pool ledger terminated
    PoolLedgerTerminated = 302,

    // No consensus during ledger operation
    LedgerNoConsensusError = 303,

    // Attempt to parse invalid transaction response
    LedgerInvalidTransaction = 304,

    // Attempt to send transaction without the necessary privileges
    LedgerSecurityError = 305,

    // Attempt to create pool ledger config with name used for another existing pool
    PoolLedgerConfigAlreadyExistsError = 306,

    // Timeout for action
    PoolLedgerTimeout = 307,

    // Revocation registry is full and creation of new registry is necessary
    AnoncredsRevocationRegistryFullError = 400,

    AnoncredsInvalidUserRevocId = 401,

    // Attempt to generate master secret with duplicated name
    AnoncredsMasterSecretDuplicateNameError = 404,

    AnoncredsProofRejected = 405,

    AnoncredsCredentialRevoked = 406,

    // Attempt to create credential definition with duplicated id
    AnoncredsCredDefAlreadyExistsError = 407,

    // Crypto errors
    // Unknown format of DID entity keys
    UnknownCryptoTypeError = 500,

    // Attempt to create duplicate did
    DidAlreadyExistsError = 600,

    // Unknown payment method was given
    PaymentUnknownMethodError = 700,

    //No method were scraped from inputs/outputs or more than one were scraped
    PaymentIncompatibleMethodsError = 701,

    // Insufficient funds on inputs
    PaymentInsufficientFundsError = 702,

    // No such source on a ledger
    PaymentSourceDoesNotExistError = 703,

    // Operation is not supported for payment method
    PaymentOperationNotSupportedError = 704
}
<commit_msg>comments out logging initialization<commit_after>#![cfg_attr(feature = "fatal_warnings", deny(warnings))]

extern crate libc;
extern crate rand;

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serde;

mod libindy;
#[macro_use]
mod utils;
#[macro_use]
mod payment_method;
mod services;

use std::ffi::CString;

#[no_mangle]
pub extern fn nullpay_init() -> ErrorCode {

//    if let Err(err) = utils::logger::LibnullpayLogger::init() {
//        return err;
//    }

    let payment_method_name = CString::new(payment_method::PAYMENT_METHOD_NAME).unwrap();

    libindy::payments::register_payment_method(
        payment_method_name.as_ptr(),
        payment_method::create_payment_address::handle,
        payment_method::add_request_fees::handle,
        payment_method::parse_response_with_fees::handle,
        payment_method::build_get_payment_sources_request::handle,
        payment_method::parse_get_payment_sources_response::handle,
        payment_method::build_payment_req::handle,
        payment_method::parse_payment_response::handle,
        payment_method::build_mint_req::handle,
        payment_method::build_set_txn_fees_req::handle,
        payment_method::build_get_txn_fees_req::handle,
        payment_method::parse_get_txn_fees_response::handle,
        payment_method::build_verify_payment_req::handle,
        payment_method::parse_verify_payment_response::handle,
    )
}

#[derive(Debug, PartialEq, Copy, Clone)]
#[repr(i32)]
pub enum ErrorCode
{
    Success = 0,

    // Common errors

    // Caller passed invalid value as param 1 (null, invalid json and etc..)
    CommonInvalidParam1 = 100,

    // Caller passed invalid value as param 2 (null, invalid json and etc..)
    CommonInvalidParam2 = 101,

    // Caller passed invalid value as param 3 (null, invalid json and etc..)
    CommonInvalidParam3 = 102,

    // Caller passed invalid value as param 4 (null, invalid json and etc..)
    CommonInvalidParam4 = 103,

    // Caller passed invalid value as param 5 (null, invalid json and etc..)
    CommonInvalidParam5 = 104,

    // Caller passed invalid value as param 6 (null, invalid json and etc..)
    CommonInvalidParam6 = 105,

    // Caller passed invalid value as param 7 (null, invalid json and etc..)
    CommonInvalidParam7 = 106,

    // Caller passed invalid value as param 8 (null, invalid json and etc..)
    CommonInvalidParam8 = 107,

    // Caller passed invalid value as param 9 (null, invalid json and etc..)
    CommonInvalidParam9 = 108,

    // Caller passed invalid value as param 10 (null, invalid json and etc..)
    CommonInvalidParam10 = 109,

    // Caller passed invalid value as param 11 (null, invalid json and etc..)
    CommonInvalidParam11 = 110,

    // Caller passed invalid value as param 12 (null, invalid json and etc..)
    CommonInvalidParam12 = 111,

    // Invalid library state was detected in runtime. It signals library bug
    CommonInvalidState = 112,

    // Object (json, config, key, credential and etc...) passed by library caller has invalid structure
    CommonInvalidStructure = 113,

    // IO Error
    CommonIOError = 114,

    // Caller passed invalid value as param 13 (null, invalid json and etc..)
    CommonInvalidParam13 = 115,

    // Caller passed invalid value as param 14 (null, invalid json and etc..)
    CommonInvalidParam14 = 116,

    // Wallet errors
    // Caller passed invalid wallet handle
    WalletInvalidHandle = 200,

    // Unknown type of wallet was passed on create_wallet
    WalletUnknownTypeError = 201,

    // Attempt to register already existing wallet type
    WalletTypeAlreadyRegisteredError = 202,

    // Attempt to create wallet with name used for another exists wallet
    WalletAlreadyExistsError = 203,

    // Requested entity id isn't present in wallet
    WalletNotFoundError = 204,

    // Trying to use wallet with pool that has different name
    WalletIncompatiblePoolError = 205,

    // Trying to open wallet that was opened already
    WalletAlreadyOpenedError = 206,

    // Attempt to open encrypted wallet with invalid credentials
    WalletAccessFailed = 207,

    // Input provided to wallet operations is considered not valid
    WalletInputError = 208,

    // Decoding of wallet data during input/output failed
    WalletDecodingError = 209,

    // Storage error occurred during wallet operation
    WalletStorageError = 210,

    // Error during encryption-related operations
    WalletEncryptionError = 211,

    // Requested wallet item not found
    WalletItemNotFound = 212,

    // Returned if wallet's add_record operation is used with record name that already exists
    WalletItemAlreadyExists = 213,

    // Returned if provided wallet query is invalid
    WalletQueryError = 214,

    // Ledger errors
    // Trying to open pool ledger that wasn't created before
    PoolLedgerNotCreatedError = 300,

    // Caller passed invalid pool ledger handle
    PoolLedgerInvalidPoolHandle = 301,

    // Pool ledger terminated
    PoolLedgerTerminated = 302,

    // No consensus during ledger operation
    LedgerNoConsensusError = 303,

    // Attempt to parse invalid transaction response
    LedgerInvalidTransaction = 304,

    // Attempt to send transaction without the necessary privileges
    LedgerSecurityError = 305,

    // Attempt to create pool ledger config with name used for another existing pool
    PoolLedgerConfigAlreadyExistsError = 306,

    // Timeout for action
    PoolLedgerTimeout = 307,

    // Revocation registry is full and creation of new registry is necessary
    AnoncredsRevocationRegistryFullError = 400,

    AnoncredsInvalidUserRevocId = 401,

    // Attempt to generate master secret with duplicated name
    AnoncredsMasterSecretDuplicateNameError = 404,

    AnoncredsProofRejected = 405,

    AnoncredsCredentialRevoked = 406,

    // Attempt to create credential definition with duplicated id
    AnoncredsCredDefAlreadyExistsError = 407,

    // Crypto errors
    // Unknown format of DID entity keys
    UnknownCryptoTypeError = 500,

    // Attempt to create duplicate did
    DidAlreadyExistsError = 600,

    // Unknown payment method was given
    PaymentUnknownMethodError = 700,

    //No method were scraped from inputs/outputs or more than one were scraped
    PaymentIncompatibleMethodsError = 701,

    // Insufficient funds on inputs
    PaymentInsufficientFundsError = 702,

    // No such source on a ledger
    PaymentSourceDoesNotExistError = 703,

    // Operation is not supported for payment method
    PaymentOperationNotSupportedError = 704
}
<|endoftext|>


<commit_before>// Copyright 2016 TiKV Project Authors. Licensed under Apache-2.0.

mod client;
mod feature_gate;
pub mod metrics;
mod util;

mod config;
pub mod errors;
pub use self::client::{DummyPdClient, RpcClient};
pub use self::config::Config;
pub use self::errors::{Error, Result};
pub use self::feature_gate::{Feature, FeatureGate};
pub use self::util::PdConnector;
pub use self::util::REQUEST_RECONNECT_INTERVAL;

use std::ops::Deref;

use futures::future::BoxFuture;
use kvproto::metapb;
use kvproto::pdpb;
use kvproto::replication_modepb::{RegionReplicationStatus, ReplicationStatus};
use tikv_util::time::UnixSecs;
use txn_types::TimeStamp;

pub type Key = Vec<u8>;
pub type PdFuture<T> = BoxFuture<'static, Result<T>>;

#[derive(Default, Clone)]
pub struct RegionStat {
    pub down_peers: Vec<pdpb::PeerStats>,
    pub pending_peers: Vec<metapb::Peer>,
    pub written_bytes: u64,
    pub written_keys: u64,
    pub read_bytes: u64,
    pub read_keys: u64,
    pub approximate_size: u64,
    pub approximate_keys: u64,
    pub last_report_ts: UnixSecs,
}

#[derive(Clone, Debug, PartialEq)]
pub struct RegionInfo {
    pub region: metapb::Region,
    pub leader: Option<metapb::Peer>,
}

impl RegionInfo {
    pub fn new(region: metapb::Region, leader: Option<metapb::Peer>) -> RegionInfo {
        RegionInfo { region, leader }
    }
}

impl Deref for RegionInfo {
    type Target = metapb::Region;

    fn deref(&self) -> &Self::Target {
        &self.region
    }
}

pub const INVALID_ID: u64 = 0;

/// PdClient communicates with Placement Driver (PD).
/// Because now one PD only supports one cluster, so it is no need to pass
/// cluster id in trait interface every time, so passing the cluster id when
/// creating the PdClient is enough and the PdClient will use this cluster id
/// all the time.
pub trait PdClient: Send + Sync {
    /// Returns the cluster ID.
    fn get_cluster_id(&self) -> Result<u64> {
        unimplemented!();
    }

    /// Creates the cluster with cluster ID, node, stores and first Region.
    /// If the cluster is already bootstrapped, return ClusterBootstrapped error.
    /// When a node starts, if it finds nothing in the node and
    /// cluster is not bootstrapped, it begins to create node, stores, first Region
    /// and then call bootstrap_cluster to let PD know it.
    /// It may happen that multi nodes start at same time to try to
    /// bootstrap, but only one can succeed, while others will fail
    /// and must remove their created local Region data themselves.
    fn bootstrap_cluster(
        &self,
        _stores: metapb::Store,
        _region: metapb::Region,
    ) -> Result<Option<ReplicationStatus>> {
        unimplemented!();
    }

    /// Returns whether the cluster is bootstrapped or not.
    ///
    /// Cluster must be bootstrapped when we use it, so when the
    /// node starts, `is_cluster_bootstrapped` must be called,
    /// and panics if cluster was not bootstrapped.
    fn is_cluster_bootstrapped(&self) -> Result<bool> {
        unimplemented!();
    }

    /// Allocates a unique positive id.
    fn alloc_id(&self) -> Result<u64> {
        unimplemented!();
    }

    /// Informs PD when the store starts or some store information changes.
    fn put_store(&self, _store: metapb::Store) -> Result<Option<ReplicationStatus>> {
        unimplemented!();
    }

    /// We don't need to support Region and Peer put/delete,
    /// because PD knows all Region and Peers itself:
    /// - For bootstrapping, PD knows first Region with `bootstrap_cluster`.
    /// - For changing Peer, PD determines where to add a new Peer in some store
    ///   for this Region.
    /// - For Region splitting, PD determines the new Region id and Peer id for the
    ///   split Region.
    /// - For Region merging, PD knows which two Regions will be merged and which Region
    ///   and Peers will be removed.
    /// - For auto-balance, PD determines how to move the Region from one store to another.

    /// Gets store information if it is not a tombstone store.
    fn get_store(&self, _store_id: u64) -> Result<metapb::Store> {
        unimplemented!();
    }

    /// Gets store information if it is not a tombstone store asynchronously
    fn get_store_async(&self, _store_id: u64) -> PdFuture<metapb::Store> {
        unimplemented!();
    }

    /// Gets all stores information.
    fn get_all_stores(&self, _exclude_tombstone: bool) -> Result<Vec<metapb::Store>> {
        unimplemented!();
    }

    /// Gets cluster meta information.
    fn get_cluster_config(&self) -> Result<metapb::Cluster> {
        unimplemented!();
    }

    /// For route.
    /// Gets Region which the key belongs to.
    fn get_region(&self, _key: &[u8]) -> Result<metapb::Region> {
        unimplemented!();
    }

    /// Gets Region which the key belongs to asynchronously.
    fn get_region_async<'k>(&'k self, _key: &'k [u8]) -> BoxFuture<'k, Result<metapb::Region>> {
        unimplemented!();
    }

    /// Gets Region info which the key belongs to.
    fn get_region_info(&self, _key: &[u8]) -> Result<RegionInfo> {
        unimplemented!();
    }

    /// Gets Region info which the key belongs to asynchronously.
    fn get_region_info_async<'k>(&'k self, _key: &'k [u8]) -> BoxFuture<'k, Result<RegionInfo>> {
        unimplemented!();
    }

    /// Gets Region by Region id.
    fn get_region_by_id(&self, _region_id: u64) -> PdFuture<Option<metapb::Region>> {
        unimplemented!();
    }

    /// Gets Region and its leader by Region id.
    fn get_region_leader_by_id(
        &self,
        _region_id: u64,
    ) -> PdFuture<Option<(metapb::Region, metapb::Peer)>> {
        unimplemented!();
    }

    /// Region's Leader uses this to heartbeat PD.
    fn region_heartbeat(
        &self,
        _term: u64,
        _region: metapb::Region,
        _leader: metapb::Peer,
        _region_stat: RegionStat,
        _replication_status: Option<RegionReplicationStatus>,
    ) -> PdFuture<()> {
        unimplemented!();
    }

    /// Gets a stream of Region heartbeat response.
    ///
    /// Please note that this method should only be called once.
    fn handle_region_heartbeat_response<F>(&self, _store_id: u64, _f: F) -> PdFuture<()>
    where
        Self: Sized,
        F: Fn(pdpb::RegionHeartbeatResponse) + Send + 'static,
    {
        unimplemented!();
    }

    /// Asks PD for split. PD returns the newly split Region id.
    fn ask_split(&self, _region: metapb::Region) -> PdFuture<pdpb::AskSplitResponse> {
        unimplemented!();
    }

    /// Asks PD for batch split. PD returns the newly split Region ids.
    fn ask_batch_split(
        &self,
        _region: metapb::Region,
        _count: usize,
    ) -> PdFuture<pdpb::AskBatchSplitResponse> {
        unimplemented!();
    }

    /// Sends store statistics regularly.
    fn store_heartbeat(&self, _stats: pdpb::StoreStats) -> PdFuture<pdpb::StoreHeartbeatResponse> {
        unimplemented!();
    }

    /// Reports PD the split Region.
    fn report_batch_split(&self, _regions: Vec<metapb::Region>) -> PdFuture<()> {
        unimplemented!();
    }

    /// Scatters the Region across the cluster.
    fn scatter_region(&self, _: RegionInfo) -> Result<()> {
        unimplemented!();
    }

    /// Registers a handler to the client, which will be invoked after reconnecting to PD.
    ///
    /// Please note that this method should only be called once.
    fn handle_reconnect<F: Fn() + Sync + Send + 'static>(&self, _: F)
    where
        Self: Sized,
    {
    }

    fn get_gc_safe_point(&self) -> PdFuture<u64> {
        unimplemented!();
    }

    /// Gets store state if it is not a tombstone store asynchronously.
    fn get_store_stats_async(&self, _store_id: u64) -> BoxFuture<'_, Result<pdpb::StoreStats>> {
        unimplemented!();
    }

    /// Gets current operator of the region
    fn get_operator(&self, _region_id: u64) -> Result<pdpb::GetOperatorResponse> {
        unimplemented!();
    }

    /// Gets a timestamp from PD.
    fn get_tso(&self) -> PdFuture<TimeStamp> {
        unimplemented!()
    }

    /// Gets the internal `FeatureGate`.
    fn feature_gate(&self) -> &FeatureGate {
        todo!()
    }
}

const REQUEST_TIMEOUT: u64 = 2; // 2s

/// Takes the peer address (for sending raft messages) from a store.
pub fn take_peer_address(store: &mut metapb::Store) -> String {
    if !store.get_peer_address().is_empty() {
        store.take_peer_address()
    } else {
        store.take_address()
    }
}
<commit_msg>pd_client: link PD client to tikv_alloc (#9854)<commit_after>// Copyright 2016 TiKV Project Authors. Licensed under Apache-2.0.
#[allow(unused_extern_crates)]
extern crate tikv_alloc;

mod client;
mod feature_gate;
pub mod metrics;
mod util;

mod config;
pub mod errors;
pub use self::client::{DummyPdClient, RpcClient};
pub use self::config::Config;
pub use self::errors::{Error, Result};
pub use self::feature_gate::{Feature, FeatureGate};
pub use self::util::PdConnector;
pub use self::util::REQUEST_RECONNECT_INTERVAL;

use std::ops::Deref;

use futures::future::BoxFuture;
use kvproto::metapb;
use kvproto::pdpb;
use kvproto::replication_modepb::{RegionReplicationStatus, ReplicationStatus};
use tikv_util::time::UnixSecs;
use txn_types::TimeStamp;

pub type Key = Vec<u8>;
pub type PdFuture<T> = BoxFuture<'static, Result<T>>;

#[derive(Default, Clone)]
pub struct RegionStat {
    pub down_peers: Vec<pdpb::PeerStats>,
    pub pending_peers: Vec<metapb::Peer>,
    pub written_bytes: u64,
    pub written_keys: u64,
    pub read_bytes: u64,
    pub read_keys: u64,
    pub approximate_size: u64,
    pub approximate_keys: u64,
    pub last_report_ts: UnixSecs,
}

#[derive(Clone, Debug, PartialEq)]
pub struct RegionInfo {
    pub region: metapb::Region,
    pub leader: Option<metapb::Peer>,
}

impl RegionInfo {
    pub fn new(region: metapb::Region, leader: Option<metapb::Peer>) -> RegionInfo {
        RegionInfo { region, leader }
    }
}

impl Deref for RegionInfo {
    type Target = metapb::Region;

    fn deref(&self) -> &Self::Target {
        &self.region
    }
}

pub const INVALID_ID: u64 = 0;

/// PdClient communicates with Placement Driver (PD).
/// Because now one PD only supports one cluster, so it is no need to pass
/// cluster id in trait interface every time, so passing the cluster id when
/// creating the PdClient is enough and the PdClient will use this cluster id
/// all the time.
pub trait PdClient: Send + Sync {
    /// Returns the cluster ID.
    fn get_cluster_id(&self) -> Result<u64> {
        unimplemented!();
    }

    /// Creates the cluster with cluster ID, node, stores and first Region.
    /// If the cluster is already bootstrapped, return ClusterBootstrapped error.
    /// When a node starts, if it finds nothing in the node and
    /// cluster is not bootstrapped, it begins to create node, stores, first Region
    /// and then call bootstrap_cluster to let PD know it.
    /// It may happen that multi nodes start at same time to try to
    /// bootstrap, but only one can succeed, while others will fail
    /// and must remove their created local Region data themselves.
    fn bootstrap_cluster(
        &self,
        _stores: metapb::Store,
        _region: metapb::Region,
    ) -> Result<Option<ReplicationStatus>> {
        unimplemented!();
    }

    /// Returns whether the cluster is bootstrapped or not.
    ///
    /// Cluster must be bootstrapped when we use it, so when the
    /// node starts, `is_cluster_bootstrapped` must be called,
    /// and panics if cluster was not bootstrapped.
    fn is_cluster_bootstrapped(&self) -> Result<bool> {
        unimplemented!();
    }

    /// Allocates a unique positive id.
    fn alloc_id(&self) -> Result<u64> {
        unimplemented!();
    }

    /// Informs PD when the store starts or some store information changes.
    fn put_store(&self, _store: metapb::Store) -> Result<Option<ReplicationStatus>> {
        unimplemented!();
    }

    /// We don't need to support Region and Peer put/delete,
    /// because PD knows all Region and Peers itself:
    /// - For bootstrapping, PD knows first Region with `bootstrap_cluster`.
    /// - For changing Peer, PD determines where to add a new Peer in some store
    ///   for this Region.
    /// - For Region splitting, PD determines the new Region id and Peer id for the
    ///   split Region.
    /// - For Region merging, PD knows which two Regions will be merged and which Region
    ///   and Peers will be removed.
    /// - For auto-balance, PD determines how to move the Region from one store to another.

    /// Gets store information if it is not a tombstone store.
    fn get_store(&self, _store_id: u64) -> Result<metapb::Store> {
        unimplemented!();
    }

    /// Gets store information if it is not a tombstone store asynchronously
    fn get_store_async(&self, _store_id: u64) -> PdFuture<metapb::Store> {
        unimplemented!();
    }

    /// Gets all stores information.
    fn get_all_stores(&self, _exclude_tombstone: bool) -> Result<Vec<metapb::Store>> {
        unimplemented!();
    }

    /// Gets cluster meta information.
    fn get_cluster_config(&self) -> Result<metapb::Cluster> {
        unimplemented!();
    }

    /// For route.
    /// Gets Region which the key belongs to.
    fn get_region(&self, _key: &[u8]) -> Result<metapb::Region> {
        unimplemented!();
    }

    /// Gets Region which the key belongs to asynchronously.
    fn get_region_async<'k>(&'k self, _key: &'k [u8]) -> BoxFuture<'k, Result<metapb::Region>> {
        unimplemented!();
    }

    /// Gets Region info which the key belongs to.
    fn get_region_info(&self, _key: &[u8]) -> Result<RegionInfo> {
        unimplemented!();
    }

    /// Gets Region info which the key belongs to asynchronously.
    fn get_region_info_async<'k>(&'k self, _key: &'k [u8]) -> BoxFuture<'k, Result<RegionInfo>> {
        unimplemented!();
    }

    /// Gets Region by Region id.
    fn get_region_by_id(&self, _region_id: u64) -> PdFuture<Option<metapb::Region>> {
        unimplemented!();
    }

    /// Gets Region and its leader by Region id.
    fn get_region_leader_by_id(
        &self,
        _region_id: u64,
    ) -> PdFuture<Option<(metapb::Region, metapb::Peer)>> {
        unimplemented!();
    }

    /// Region's Leader uses this to heartbeat PD.
    fn region_heartbeat(
        &self,
        _term: u64,
        _region: metapb::Region,
        _leader: metapb::Peer,
        _region_stat: RegionStat,
        _replication_status: Option<RegionReplicationStatus>,
    ) -> PdFuture<()> {
        unimplemented!();
    }

    /// Gets a stream of Region heartbeat response.
    ///
    /// Please note that this method should only be called once.
    fn handle_region_heartbeat_response<F>(&self, _store_id: u64, _f: F) -> PdFuture<()>
    where
        Self: Sized,
        F: Fn(pdpb::RegionHeartbeatResponse) + Send + 'static,
    {
        unimplemented!();
    }

    /// Asks PD for split. PD returns the newly split Region id.
    fn ask_split(&self, _region: metapb::Region) -> PdFuture<pdpb::AskSplitResponse> {
        unimplemented!();
    }

    /// Asks PD for batch split. PD returns the newly split Region ids.
    fn ask_batch_split(
        &self,
        _region: metapb::Region,
        _count: usize,
    ) -> PdFuture<pdpb::AskBatchSplitResponse> {
        unimplemented!();
    }

    /// Sends store statistics regularly.
    fn store_heartbeat(&self, _stats: pdpb::StoreStats) -> PdFuture<pdpb::StoreHeartbeatResponse> {
        unimplemented!();
    }

    /// Reports PD the split Region.
    fn report_batch_split(&self, _regions: Vec<metapb::Region>) -> PdFuture<()> {
        unimplemented!();
    }

    /// Scatters the Region across the cluster.
    fn scatter_region(&self, _: RegionInfo) -> Result<()> {
        unimplemented!();
    }

    /// Registers a handler to the client, which will be invoked after reconnecting to PD.
    ///
    /// Please note that this method should only be called once.
    fn handle_reconnect<F: Fn() + Sync + Send + 'static>(&self, _: F)
    where
        Self: Sized,
    {
    }

    fn get_gc_safe_point(&self) -> PdFuture<u64> {
        unimplemented!();
    }

    /// Gets store state if it is not a tombstone store asynchronously.
    fn get_store_stats_async(&self, _store_id: u64) -> BoxFuture<'_, Result<pdpb::StoreStats>> {
        unimplemented!();
    }

    /// Gets current operator of the region
    fn get_operator(&self, _region_id: u64) -> Result<pdpb::GetOperatorResponse> {
        unimplemented!();
    }

    /// Gets a timestamp from PD.
    fn get_tso(&self) -> PdFuture<TimeStamp> {
        unimplemented!()
    }

    /// Gets the internal `FeatureGate`.
    fn feature_gate(&self) -> &FeatureGate {
        todo!()
    }
}

const REQUEST_TIMEOUT: u64 = 2; // 2s

/// Takes the peer address (for sending raft messages) from a store.
pub fn take_peer_address(store: &mut metapb::Store) -> String {
    if !store.get_peer_address().is_empty() {
        store.take_peer_address()
    } else {
        store.take_address()
    }
}
<|endoftext|>


<commit_before>pub mod vec {
    use ::{Transducer, TransductionResult};

    pub trait Ref {
        type Input;

        fn trans_ref<'a, T, O>(&'a self, transducer: T) -> Vec<O>
            where T: Transducer<&'a Self::Input, O>;
    }

    impl<X> Ref for Vec<X> {
        type Input = X;

        fn trans_ref<'a, T, O>(&'a self, mut transducer: T) -> Vec<O>
            where T: Transducer<&'a Self::Input, O> {

            let mut result = Vec::with_capacity(self.len());
            for val in self {
                match transducer.accept(Some(val)) {
                    TransductionResult::End => { return result; },
                    TransductionResult::None => (),
                    TransductionResult::Some(r) => { result.push(r); }
                }
            }
            loop {
                match transducer.accept(None) {
                    TransductionResult::End => { return result; },
                    TransductionResult::None => (),
                    TransductionResult::Some(r) => { result.push(r); }
                }
            }
        }
    }

    pub trait Drain {
        type Input;

        fn trans_drain<T, O>(mut self, transducer: T) -> Vec<O>
            where T: Transducer<Self::Input, O>;
    }

    impl<X> Drain for Vec<X> {
        type Input = X;

        fn trans_drain<T, O>(mut self, mut transducer: T) -> Vec<O>
            where T: Transducer<Self::Input, O> {

            let mut result = Vec::with_capacity(self.len());
            for val in self.drain(..) {
                match transducer.accept(Some(val)) {
                    TransductionResult::End => { return result; },
                    TransductionResult::None => (),
                    TransductionResult::Some(r) => { result.push(r); }
                }
            }
            loop {
                match transducer.accept(None) {
                    TransductionResult::End => { return result; },
                    TransductionResult::None => (),
                    TransductionResult::Some(r) => { result.push(r); }
                }
            }
        }
    }
}
<commit_msg>Transduce an iterator<commit_after>pub mod vec {
    use ::{Transducer, TransductionResult};

    pub trait Ref {
        type Input;

        fn trans_ref<'a, T, O>(&'a self, transducer: T) -> Vec<O>
            where T: Transducer<&'a Self::Input, O>;
    }

    impl<X> Ref for Vec<X> {
        type Input = X;

        fn trans_ref<'a, T, O>(&'a self, mut transducer: T) -> Vec<O>
            where T: Transducer<&'a Self::Input, O> {

            let mut result = Vec::with_capacity(self.len());
            for val in self {
                match transducer.accept(Some(val)) {
                    TransductionResult::End => { return result; },
                    TransductionResult::None => (),
                    TransductionResult::Some(r) => { result.push(r); }
                }
            }
            loop {
                match transducer.accept(None) {
                    TransductionResult::End => { return result; },
                    TransductionResult::None => (),
                    TransductionResult::Some(r) => { result.push(r); }
                }
            }
        }
    }

    pub trait Drain {
        type Input;

        fn trans_drain<T, O>(mut self, transducer: T) -> Vec<O>
            where T: Transducer<Self::Input, O>;
    }

    impl<X> Drain for Vec<X> {
        type Input = X;

        fn trans_drain<T, O>(mut self, mut transducer: T) -> Vec<O>
            where T: Transducer<Self::Input, O> {

            let mut result = Vec::with_capacity(self.len());
            for val in self.drain(..) {
                match transducer.accept(Some(val)) {
                    TransductionResult::End => { return result; },
                    TransductionResult::None => (),
                    TransductionResult::Some(r) => { result.push(r); }
                }
            }
            loop {
                match transducer.accept(None) {
                    TransductionResult::End => { return result; },
                    TransductionResult::None => (),
                    TransductionResult::Some(r) => { result.push(r); }
                }
            }
        }
    }
}

pub mod iter {
    use std::marker::PhantomData;

    use ::{Transducer, TransductionResult};

    pub trait TransduceIter {
        type UnderlyingIterator;

        fn transduce<T, F, O>(self, transducer: T) -> TransduceIterator<Self::UnderlyingIterator, T, F, O>
            where T: Transducer<F, O>;
    }

    impl<I> TransduceIter for I
        where I: Iterator {

        type UnderlyingIterator = I;

        fn transduce<T, F, O>(self, transducer: T) -> TransduceIterator<Self::UnderlyingIterator, T, F, O>
            where T: Transducer<F, O> {

            TransduceIterator {
                underlying: self,
                finished: false,
                transducer: transducer,
                from: PhantomData,
                out: PhantomData
            }
        }
    }

    pub struct TransduceIterator<I, T, F, O> {
        underlying: I,
        finished: bool,
        transducer: T,
        from: PhantomData<F>,
        out: PhantomData<O>
    }

    impl<I, T, F, O> TransduceIterator<I, T, F, O>
        where T: Transducer<F, O> {
    }

    impl<I, T, F, O> Iterator for TransduceIterator<I, T, F, O>
        where I: Iterator<Item=F>,
              T: Transducer<F, O> {

        type Item = O;

        #[inline]
        fn next(&mut self) -> Option<Self::Item> {
            loop {
                let next_val = if self.finished {
                    None
                } else {
                    let interim = self.underlying.next();
                    if interim.is_none() {
                        self.finished = true
                    }
                    interim
                };
                match self.transducer.accept(next_val) {
                    TransductionResult::End => return None,
                    TransductionResult::None => (),
                    TransductionResult::Some(value) => return Some(value)
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// useful for debugging:
// strace -fo logfile /path/to/exe
// strace -fe mmap /path/to/executable

use std::ptr;
use std::fs;
use std::io::{Write, SeekFrom, Seek};
use std::os::unix::prelude::AsRawFd;
use mmap::{MemoryMap, MapOption};
use std::thread;

// from crates.io
extern crate mmap;
extern crate libc;

fn toggle(data: *mut u8, led_pin: u32) {
    unsafe {
        *(data.offset(0x30) as *mut u32) ^= 1 << led_pin;
    }
}

fn main() {
    let size: usize = 0x7FFFFF; // i want to access the memory from 0x40000000 to 0x407FFFFF

    let mut f = fs::OpenOptions::new().read(true)
                                      .write(true)
                                      .open("/dev/mem")
                                      .unwrap();

    let mmap_opts = &[
        // Then make the mapping *public* so it is written back to the file
        MapOption::MapNonStandardFlags(libc::MAP_SHARED), //consts::os::posix88::MAP_SHARED),
        MapOption::MapNonStandardFlags(libc::consts::os::extra::O_SYNC),
        MapOption::MapReadable,
        MapOption::MapWritable,
        MapOption::MapOffset(0x40000000),
        MapOption::MapFd(f.as_raw_fd()),
    ];

    let mmap = MemoryMap::new(size, mmap_opts).unwrap();

    let data = mmap.data();

    if data.is_null() {
        panic!("Could not access data from memory mapped file")
    }
    else {
        println!("successful data access to memory mapped file");
    }

    while (true) {
        toggle(data, 3);
        thread::sleep_ms(200);
    }
}<commit_msg>removed flag<commit_after>// useful for debugging:
// strace -fo logfile /path/to/exe
// strace -fe mmap /path/to/executable

use std::ptr;
use std::fs;
use std::io::{Write, SeekFrom, Seek};
use std::os::unix::prelude::AsRawFd;
use mmap::{MemoryMap, MapOption};
use std::thread;

// from crates.io
extern crate mmap;
extern crate libc;

fn toggle(data: *mut u8, led_pin: u32) {
    unsafe {
        *(data.offset(0x30) as *mut u32) ^= 1 << led_pin;
    }
}

fn main() {
    let size: usize = 0x7FFFFF; // i want to access the memory from 0x40000000 to 0x407FFFFF

    let mut f = fs::OpenOptions::new().read(true)
                                      .write(true)
                                      .open("/dev/mem")
                                      .unwrap();

    let mmap_opts = &[
        // Then make the mapping *public* so it is written back to the file
        MapOption::MapNonStandardFlags(libc::MAP_SHARED),
        MapOption::MapReadable,
        MapOption::MapWritable,
        MapOption::MapOffset(0x40000000),
        MapOption::MapFd(f.as_raw_fd()),
    ];

    let mmap = MemoryMap::new(size, mmap_opts).unwrap();

    let data = mmap.data();

    if data.is_null() {
        panic!("Could not access data from memory mapped file")
    }
    else {
        println!("successful data access to memory mapped file");
    }

    while (true) {
        toggle(data, 3);
        thread::sleep_ms(200);
    }
}<|endoftext|>