use bytes::Bytes;
use serde::Deserialize;
use serde::Serialize;
use url::Url;
use super::ProviderReference;
use super::base64_bytes;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "kebab-case")]
#[non_exhaustive]
pub enum FileData {
#[serde(rename = "data")]
Bytes {
#[serde(with = "base64_bytes")]
data: Bytes,
},
Url {
url: Url,
},
Reference {
reference: ProviderReference,
},
Text {
text: String,
},
}
impl FileData {
#[must_use]
pub fn bytes(data: impl Into<Bytes>) -> Self {
Self::Bytes { data: data.into() }
}
pub fn from_base64(text: &str) -> Result<Self, base64::DecodeError> {
base64_bytes::decode(text).map(|data| Self::Bytes { data })
}
#[must_use]
pub fn url(url: Url) -> Self {
Self::Url { url }
}
#[must_use]
pub fn reference(provider: impl Into<String>, id: impl Into<String>) -> Self {
let mut map = ProviderReference::new();
map.insert(provider.into(), id.into());
Self::Reference { reference: map }
}
#[must_use]
pub fn text(text: impl Into<String>) -> Self {
Self::Text { text: text.into() }
}
#[must_use]
pub fn as_bytes(&self) -> Option<&Bytes> {
match self {
Self::Bytes { data } => Some(data),
Self::Url { .. } | Self::Reference { .. } | Self::Text { .. } => None,
}
}
#[must_use]
pub fn as_url(&self) -> Option<&Url> {
match self {
Self::Url { url } => Some(url),
Self::Bytes { .. } | Self::Reference { .. } | Self::Text { .. } => None,
}
}
#[must_use]
pub fn as_reference(&self) -> Option<&ProviderReference> {
match self {
Self::Reference { reference } => Some(reference),
Self::Bytes { .. } | Self::Url { .. } | Self::Text { .. } => None,
}
}
#[must_use]
pub fn as_text(&self) -> Option<&str> {
match self {
Self::Text { text } => Some(text),
Self::Bytes { .. } | Self::Url { .. } | Self::Reference { .. } => None,
}
}
#[must_use]
pub fn to_base64(&self) -> Option<String> {
self.as_bytes().map(|bytes| base64_bytes::encode(bytes))
}
}
impl From<Bytes> for FileData {
fn from(data: Bytes) -> Self {
Self::Bytes { data }
}
}
impl From<Vec<u8>> for FileData {
fn from(bytes: Vec<u8>) -> Self {
Self::Bytes {
data: Bytes::from(bytes),
}
}
}
impl From<Url> for FileData {
fn from(url: Url) -> Self {
Self::Url { url }
}
}
impl From<ProviderReference> for FileData {
fn from(reference: ProviderReference) -> Self {
Self::Reference { reference }
}
}