frpc-lib 0.1.0

Library for Fluid RPC to dynamically invoke gRPC services
Documentation
use std::error::Error;

use anyhow::Result;

use super::{reflection_loader_v1, reflection_loader_v1alpha};

#[derive(Debug)]
pub enum TryGetReflectionVersionResponse {
    DetectedVersion(ReflectionVersion),
    VersionUndetectable,
    ConnectionError { error: Box<dyn Error + Send + Sync> },
}

#[derive(Debug)]
pub enum ReflectionVersion {
    V1,
    V1Alpha,
}

pub(crate) async fn try_get_reflection_version(
    server_url: String,
) -> Result<TryGetReflectionVersionResponse> {
    let v1_implemented = reflection_loader_v1::check_implemented(server_url.clone()).await;

    match v1_implemented {
        Ok(true) => {
            return Ok(TryGetReflectionVersionResponse::DetectedVersion(
                ReflectionVersion::V1,
            ))
        }
        Ok(_) => {}
        Err(e) => {
            if let Some(transport) = &e.downcast_ref::<tonic::transport::Error>() {
                let source = transport.source();

                match source {
                    Some(source) => {
                        if source.is::<tonic::ConnectError>() {
                            return Ok(TryGetReflectionVersionResponse::ConnectionError {
                                error: e.into(),
                            });
                        }
                    }
                    None => {}
                };
            }
        }
    };

    let v1alpha_implemented = reflection_loader_v1alpha::check_implemented(server_url).await;

    match v1alpha_implemented {
        Ok(true) => {
            return Ok(TryGetReflectionVersionResponse::DetectedVersion(
                ReflectionVersion::V1Alpha,
            ))
        }
        Ok(_) => {}
        Err(e) => {
            if let Some(transport) = &e.downcast_ref::<tonic::transport::Error>() {
                let source = transport.source();

                match source {
                    Some(source) => {
                        if source.is::<tonic::ConnectError>() {
                            return Ok(TryGetReflectionVersionResponse::ConnectionError {
                                error: e.into(),
                            });
                        }
                    }
                    None => {}
                };
            }
        }
    };

    Ok(TryGetReflectionVersionResponse::VersionUndetectable)
}