minio-rsc 0.1.1

rust for minio
Documentation
mod complete_multipart_upload_result;
mod initiate_multipart_upload_result;
mod list_buckets_response;
mod list_multipart_uploads_result;
mod list_objects_response;
mod list_parts_result;
use std::io::Cursor;
use std::ops::IndexMut;

pub use complete_multipart_upload_result::*;
pub use initiate_multipart_upload_result::*;
pub use list_buckets_response::*;
pub use list_multipart_uploads_result::*;
pub use list_objects_response::*;
pub use list_parts_result::*;
use quick_xml::events::BytesText;
use quick_xml::Writer;
use serde::Deserialize;
use serde::Serialize;

use crate::errors::XmlError;
use crate::utils::urlencode;

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
pub struct Tag {
    pub key: String,
    pub value: String,
}

impl Tag {
    pub fn new<T1: Into<String>, T2: Into<String>>(key: T1, value: T2) -> Self {
        Self {
            key: key.into(),
            value: value.into(),
        }
    }
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
struct TagSet {
    #[serde(rename = "Tag", default)]
    tags: Vec<Tag>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
pub struct Tagging {
    tag_set: TagSet,
}

impl Tagging {
    pub fn new() -> Self {
        Self {
            tag_set: TagSet { tags: Vec::new() },
        }
    }

    pub fn tags(&self) -> &Vec<Tag> {
        &self.tag_set.tags
    }

    pub fn insert<T1: Into<String>, T2: Into<String>>(&mut self, key: T1, value: T2) -> &mut Self {
        let key: String = key.into();
        let value: String = value.into();
        if !key.is_empty() && !value.is_empty() {
            let mut i = 0;
            for t in &self.tag_set.tags {
                if t.key == key {
                    break;
                }
                i = i + 1;
            }
            if i >= self.tag_set.tags.len() {
                self.tag_set.tags.push(Tag::new(key, value))
            } else {
                self.tag_set.tags.index_mut(i).value = value;
            }
        }
        self
    }

    pub fn remove<T1: Into<String>>(&mut self, key: T1) -> Option<Tag> {
        let key: String = key.into();
        let mut i = 0;
        let mut find = false;
        for t in &self.tag_set.tags {
            if t.key == key {
                find = true;
                break;
            }
            i = i + 1;
        }
        if find {
            Some(self.tag_set.tags.remove(i))
        } else {
            None
        }
    }

    pub fn to_xml(self) -> Result<Vec<u8>, XmlError> {
        let mut writer = Writer::new(Cursor::new(Vec::new()));
        writer
            .create_element("Tagging")
            .write_inner_content(|writer| {
                writer.create_element("TagSet").write_inner_content(|w| {
                    for s in self.tags() {
                        w.create_element("Tag").write_inner_content(|w| {
                            w.create_element("Key")
                                .write_text_content(BytesText::new(&s.key))?;
                            w.create_element("Value")
                                .write_text_content(BytesText::new(&s.value))?;
                            Ok(())
                        })?;
                    }
                    Ok(())
                })?;
                Ok(())
            })?;
        Ok(writer.into_inner().into_inner())
    }
    pub fn to_query(&self) -> Option<String> {
        let query: String = self
            .tags()
            .iter()
            .map(|t| {
                format!(
                    "{}={}",
                    urlencode(&t.key, false),
                    urlencode(&t.value, false)
                )
            })
            .collect::<Vec<String>>()
            .join("=");
        if query.is_empty() {
            None
        } else {
            Some(query)
        }
    }
}

impl TryFrom<&str> for Tagging {
    type Error = XmlError;
    fn try_from(value: &str) -> Result<Self, Self::Error> {
        quick_xml::de::from_str(&value).map_err(|x| x.into())
    }
}

impl TryInto<String> for Tagging {
    type Error = XmlError;

    fn try_into(self) -> Result<String, Self::Error> {
        quick_xml::se::to_string(&self).map_err(|x| x.into())
    }
}