ydb 0.12.0

Crate contains generated low-level grpc code from YDB API protobuf, used as base for ydb crate
Documentation
use crate::client_common::{DBCredentials, TokenCache};
use crate::grpc_wrapper::raw_errors::{RawError, RawResult};
use crate::grpc_wrapper::runtime_interceptors::{
    GrpcInterceptor, InterceptorError, InterceptorRequest, InterceptorResult, RequestMetadata,
};
use http::HeaderValue;
use secrecy::ExposeSecret;

pub(crate) struct AuthGrpcInterceptor {
    db_name: HeaderValue,
    token_cache: TokenCache,
}
const VERSION_LABEL: &str = concat!("ydb-rust-sdk/", env!("CARGO_PKG_VERSION"));

impl AuthGrpcInterceptor {
    pub fn new(cred: DBCredentials) -> RawResult<AuthGrpcInterceptor> {
        let db_name = HeaderValue::from_str(cred.database.as_str()).map_err(|err| {
            RawError::custom(format!(
                "bad db name for set in headers '{}': {}",
                cred.database.as_str(),
                err
            ))
        })?;

        Ok(AuthGrpcInterceptor {
            db_name,
            token_cache: cred.token_cache,
        })
    }
}

impl GrpcInterceptor for AuthGrpcInterceptor {
    fn on_call(
        &self,
        _metadata: &mut RequestMetadata,
        mut req: InterceptorRequest,
    ) -> InterceptorResult<InterceptorRequest> {
        let token_secret = self.token_cache.token();
        let token_string = token_secret.expose_secret();
        let token = HeaderValue::from_str(token_string.as_str()).map_err(|err| {
            InterceptorError::custom(format!(
                "received bad token (len={}): {}",
                token_string.len(),
                err
            ))
        })?;

        req.headers_mut()
            .insert("x-ydb-database", self.db_name.clone());
        req.headers_mut().insert(
            "x-ydb-sdk-build-info",
            HeaderValue::from_static(VERSION_LABEL),
        );
        req.headers_mut().insert("x-ydb-auth-ticket", token);
        Ok(req)
    }
}