z_osmf 0.13.5

The Rust z/OSMF Client
Documentation
use std::marker::PhantomData;
use std::sync::Arc;

use bytes::Bytes;
use z_osmf_macros::Endpoint;

use crate::convert::TryFromResponse;
use crate::ClientCore;

use super::{get_member, get_volume, DatasetEnqueue, DatasetMigratedRecall};

#[derive(Clone, Debug, Endpoint)]
#[endpoint(method = put, path = "/zosmf/restfiles/ds{volume}/{dataset}{member}")]
pub struct DatasetWriteBuilder<T>
where
    T: TryFromResponse,
{
    core: Arc<ClientCore>,

    #[endpoint(path)]
    dataset: Arc<str>,
    #[endpoint(path, builder_fn = build_volume)]
    volume: Option<Arc<str>>,
    #[endpoint(path, builder_fn = build_member)]
    member: Option<Arc<str>>,
    #[endpoint(header = "If-Match")]
    if_match: Option<Arc<str>>,
    #[endpoint(skip_setter, builder_fn = build_data)]
    data: Option<Data>,
    #[endpoint(skip_builder)]
    encoding: Option<Arc<str>>,
    #[endpoint(skip_builder)]
    crlf_newlines: Option<bool>,
    #[endpoint(header = "X-IBM-Migrated-Recall")]
    migrated_recall: Option<DatasetMigratedRecall>,
    #[endpoint(header = "X-IBM-Obtain-ENQ")]
    obtain_enq: Option<DatasetEnqueue>,
    #[endpoint(header = "X-IBM-Session-Ref")]
    session_ref: Option<Arc<str>>,
    #[endpoint(builder_fn = build_release_enq)]
    release_enq: Option<bool>,
    #[endpoint(header = "X-IBM-Dsname-Encoding")]
    dsname_encoding: Option<Arc<str>>,

    target_type: PhantomData<T>,
}

impl<T> DatasetWriteBuilder<T>
where
    T: TryFromResponse,
{
    pub fn binary<B>(self, data: B) -> Self
    where
        B: Into<Bytes>,
    {
        DatasetWriteBuilder {
            data: Some(Data::Binary(data.into())),
            ..self
        }
    }

    pub fn record<B>(self, data: B) -> Self
    where
        B: Into<Bytes>,
    {
        DatasetWriteBuilder {
            data: Some(Data::Record(data.into())),
            ..self
        }
    }

    pub fn text<S>(self, data: S) -> Self
    where
        S: std::fmt::Display,
    {
        DatasetWriteBuilder {
            data: Some(Data::Text(data.to_string())),
            ..self
        }
    }
}

#[derive(Clone, Debug)]
enum Data {
    Binary(Bytes),
    Record(Bytes),
    Text(String),
}

fn build_data<T>(
    request_builder: reqwest::RequestBuilder,
    builder: &DatasetWriteBuilder<T>,
) -> reqwest::RequestBuilder
where
    T: TryFromResponse,
{
    let DatasetWriteBuilder {
        data,
        encoding,
        crlf_newlines,
        ..
    } = builder;

    match data {
        Some(Data::Binary(binary)) => request_builder
            .header("X-IBM-Data-Type", "binary")
            .body(binary.clone()),
        Some(Data::Record(record)) => request_builder
            .header("X-IBM-Data-Type", "record")
            .body(record.clone()),
        Some(Data::Text(text)) => match (encoding, crlf_newlines) {
            (Some(encoding), Some(true)) => request_builder.header(
                "X-IBM-Data-Type",
                format!("text;fileEncoding={};crlf=true", encoding),
            ),
            (Some(encoding), _) => {
                request_builder.header("X-IBM-Data-Type", format!("text;fileEncoding={}", encoding))
            }
            (None, Some(true)) => request_builder.header("X-IBM-Data-Type", "text;crlf=true"),
            _ => request_builder,
        }
        .body(text.clone()),
        None => request_builder,
    }
}

fn build_member<T>(builder: &DatasetWriteBuilder<T>) -> String
where
    T: TryFromResponse,
{
    get_member(&builder.member)
}

fn build_release_enq<T>(
    request_builder: reqwest::RequestBuilder,
    builder: &DatasetWriteBuilder<T>,
) -> reqwest::RequestBuilder
where
    T: TryFromResponse,
{
    match builder.release_enq {
        Some(true) => request_builder.header("X-IBM-Release-ENQ", "true"),
        _ => request_builder,
    }
}

fn build_volume<T>(builder: &DatasetWriteBuilder<T>) -> String
where
    T: TryFromResponse,
{
    get_volume(&builder.volume)
}

#[cfg(test)]
mod tests {
    use crate::tests::*;

    #[test]
    fn example_1() {
        let zosmf = get_zosmf();

        let string_data = "here is some text!";

        let manual_request = zosmf
            .core
            .client
            .put("https://test.com/zosmf/restfiles/ds/SYS1.PARMLIB(SMFPRM00)")
            .header("If-Match", "B5C6454F783590AA8EC15BD88E29EA63")
            .body(string_data)
            .build()
            .unwrap();

        let write_dataset = zosmf
            .datasets()
            .write("SYS1.PARMLIB")
            .member("SMFPRM00")
            .if_match("B5C6454F783590AA8EC15BD88E29EA63")
            .text(string_data)
            .get_request()
            .unwrap();

        assert_eq!(
            format!("{:?}", manual_request),
            format!("{:?}", write_dataset)
        );

        assert_eq!(
            manual_request.body().unwrap().as_bytes().unwrap(),
            write_dataset.body().unwrap().as_bytes().unwrap()
        )
    }
}