chunky-bits 0.2.0

Chunky Bits is simple, unmanaged, distributed HTTP object store tool.
use serde::{
    Deserialize,
    Serialize,
};

use crate::file::{
    LocationContext,
    LocationContextBuilder,
};

#[derive(Clone, Serialize, Deserialize)]
#[serde(from = "TunablesInner")]
#[serde(into = "TunablesInner")]
pub struct Tunables {
    inner: TunablesInner,
    location_context: LocationContext,
}

impl AsRef<LocationContext> for Tunables {
    fn as_ref(&self) -> &LocationContext {
        &self.location_context
    }
}

impl From<TunablesInner> for Tunables {
    fn from(inner: TunablesInner) -> Self {
        Tunables {
            location_context: inner.generate_location_context_builder().build(),
            inner,
        }
    }
}

impl From<Tunables> for TunablesInner {
    fn from(t: Tunables) -> Self {
        t.inner
    }
}

impl Default for Tunables {
    fn default() -> Self {
        TunablesInner::default().into()
    }
}

impl Tunables {
    pub(super) fn generate_location_context_builder(&self) -> LocationContextBuilder {
        self.inner.generate_location_context_builder()
    }
}

#[derive(Clone, Serialize, Deserialize)]
struct TunablesInner {
    #[serde(default = "TunablesInner::https_only")]
    https_only: bool,
    #[serde(default = "TunablesInner::user_agent")]
    user_agent: Option<String>,
}

macro_rules! default_getters {
    ($($field:ident: $type:ty),*,) => {
        impl TunablesInner {
            $(
                fn $field() -> $type {
                    <TunablesInner as Default>::default().$field
                }
            )*
        }
    };
}

default_getters! {
    https_only: bool,
    user_agent: Option<String>,
}

impl Default for TunablesInner {
    fn default() -> Self {
        TunablesInner {
            https_only: false,
            user_agent: None,
        }
    }
}

impl TunablesInner {
    fn generate_location_context_builder(&self) -> LocationContextBuilder {
        let http_client = {
            let mut builder = reqwest::Client::builder();
            builder = builder.https_only(self.https_only);
            if let Some(user_agent) = &self.user_agent {
                builder = builder.user_agent(user_agent.clone())
            }
            builder.build().unwrap()
        };
        LocationContext::builder().http_client(http_client)
    }
}