ice-rs 0.3.0

ZeroC Ice for Rust
Documentation
use std::hash::Hash;

use crate::{errors::*, protocol::{EndPointType, EndpointData}};
use pest::{Parser, iterators::Pairs};


#[derive(Parser)]
#[grammar = "proxystring.pest"]
pub struct ProxyParser;



pub struct DirectProxyData {
    pub ident: String,
    pub endpoint: EndPointType,
}

pub struct IndirectProxyData {
    pub ident: String,
    pub adapter: Option<String>,
}

pub enum ProxyStringType {
    DirectProxy(DirectProxyData),
    IndirectProxy(IndirectProxyData)
}

pub fn parse_proxy_string(proxy_string: &str) -> Result<ProxyStringType, Box<dyn std::error::Error + Sync + Send>> {
    let result = ProxyParser::parse(Rule::proxystring, proxy_string)?.next().unwrap();
    for child in result.into_inner() {
        match child.as_rule() {
            Rule::direct_proxy => return parse_direct_proxy(child.into_inner()),
            Rule::indirect_proxy => return parse_indirect_proxy(child.into_inner()),
            _ => {}
        }
    }
    Err(Box::new(ParsingError::new("Unexpected rule while parsing proxy string.")))
}

pub fn parse_direct_proxy(rules: Pairs<Rule>) -> Result<ProxyStringType, Box<dyn std::error::Error + Sync + Send>> {
    let mut ident = "";
    for child in rules {
        match child.as_rule() {
            Rule::ident => {
                ident = child.as_str();
            },
            Rule::endpoint => {
                return Ok(
                    ProxyStringType::DirectProxy(
                        DirectProxyData {
                            ident: String::from(ident),
                            endpoint: parse_endpoint(child.into_inner())?
                        }
                    )
                )
            }
            _ => {}
        }
    }
    Err(Box::new(ParsingError::new("Unexpected rule while parsing proxy string.")))
}

pub fn parse_indirect_proxy(rules: Pairs<Rule>) -> Result<ProxyStringType, Box<dyn std::error::Error + Sync + Send>> {
    let mut ident = "";
    let mut adapter = None;

    for child in rules {
        match child.as_rule() {
            Rule::ident => {
                ident = child.as_str();
            },
            Rule::adapter => {
                for child in child.into_inner() {
                    match child.as_rule() {
                        Rule::keyword_at => {}
                        Rule::ident => {
                            adapter = Some(child.as_str())
                        },
                        _ => return Err(Box::new(ParsingError::new("Unexpected rule while parsing proxy string.")))
                    }
                }
            },
            _ => return Err(Box::new(ParsingError::new("Unexpected rule while parsing proxy string.")))
        }
    }

    Ok(
        ProxyStringType::IndirectProxy(IndirectProxyData {
            ident: String::from(ident),
            adapter: if adapter.is_some() { Some(String::from(adapter.unwrap())) } else { None }
        })
    )

}

pub fn parse_endpoint(rules: Pairs<Rule>) -> Result<EndPointType, Box<dyn std::error::Error + Sync + Send>> {
    let mut protocol = "";
    let mut host = "";
    let mut port = 0i32;

    for child in rules {
        match child.as_rule() {
            Rule::endpoint_protocol => {
                protocol = child.as_str();
            }
            Rule::endpoint_host | Rule::endpoint_port => {
                for item in child.into_inner() {
                    match item.as_rule() {
                        Rule::hostname | Rule::ip => {
                            host = item.as_str();
                        }
                        Rule::port => {
                            port = item.as_str().parse()?;
                        }
                        _ => return Err(Box::new(ParsingError::new(&format!("Unexpected proxy string rule: {:?}", item.as_rule()))))
                    };
                }
            }
            _ => return Err(Box::new(ParsingError::new("Unexpected rule while parsing proxy string.")))
        }
    }

    let endpoint_data = EndpointData {
        host: String::from(host),
        port,
        timeout: 60000,
        compress: false
    };

    match protocol {
        "tcp" | "default" => return Ok(EndPointType::TCP(endpoint_data)),
        "ssl" => return Ok(EndPointType::SSL(endpoint_data)),
        _ => return Err(Box::new(ParsingError::new("Unsupported protocol.")))
    }
}