use std::fmt::{Display, Formatter};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
const ADTP_VERSION: &str = "ADTP/0.0";
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn requests_test() {
let request = Request::create(Method::Create, "buss://napture.web".to_string(), "test/0.0".to_string()).with_content_string(ContentType::Text, "Content".to_string()).with_language("us-english".to_string());
assert_eq!(request.clone().build().as_str(), Request::try_from(request.build()).unwrap().build().as_str());
}
#[test]
fn responses_test() {
let response = Response::create(Status::Ok, "test/0.0".to_string()).with_language("us-english".to_string()).with_content_string(ContentType::Text, "Content".to_string());
assert_eq!(response.clone().build().as_str(), Response::try_from(response.build()).unwrap().build().as_str());
}
}
#[derive(Debug,Clone, Serialize, Deserialize)]
pub enum Method {
#[serde(rename = "read")]
Read,
#[serde(rename = "create")]
Create,
#[serde(rename = "update")]
Update,
#[serde(rename = "destroy")]
Destroy,
#[serde(rename = "check")]
Check,
#[serde(rename = "auth")]
Auth
}
#[derive(Debug,Clone, Serialize, Deserialize)]
pub enum ContentType {
#[serde(rename = "aac")]
AAC,
#[serde(rename = "avif")]
AVIF,
#[serde(rename = "avi")]
AVI,
#[serde(rename = "binary")]
Binary,
#[serde(rename = "bmp")]
BMP,
#[serde(rename = "css")]
CSS,
#[serde(rename = "csv")]
CSV,
#[serde(rename = "docx")]
DOCX,
#[serde(rename = "epub")]
EPUB,
#[serde(rename = "gif")]
GIF,
#[serde(rename = "html")]
HTML,
#[serde(rename = "ico")]
ICO,
#[serde(rename = "jpeg")]
JPEG,
#[serde(rename = "javascript")]
JavaScript,
#[serde(rename = "json")]
JSON,
#[serde(rename = "markdown")]
MarkDown,
#[serde(rename = "midi")]
MIDI,
#[serde(rename = "mp3")]
MP3,
#[serde(rename = "mp4")]
MP4,
#[serde(rename = "mpeg")]
MPEG,
#[serde(rename = "odp")]
ODP,
#[serde(rename = "ods")]
ODS,
#[serde(rename = "odt")]
ODT,
#[serde(rename = "oga")]
OGA,
#[serde(rename = "ogv")]
OGV,
#[serde(rename = "ogx")]
OGX,
#[serde(rename = "opus")]
Opus,
#[serde(rename = "otf")]
OTF,
#[serde(rename = "png")]
PNG,
#[serde(rename = "pdf")]
PDF,
#[serde(rename = "php")]
PHP,
#[serde(rename = "pptx")]
PPTX,
#[serde(rename = "rar")]
RAR,
#[serde(rename = "svg")]
SVG,
#[serde(rename = "tar")]
TAR,
#[serde(rename = "tiff")]
TIFF,
#[serde(rename = "ttf")]
TTF,
#[serde(rename = "text")]
Text,
#[serde(rename = "wav")]
WAV,
#[serde(rename = "weba")]
WEBA,
#[serde(rename = "webm")]
WEBM,
#[serde(rename = "webp")]
WEBP,
#[serde(rename = "woff")]
WOFF,
#[serde(rename = "xlsx")]
XLSX,
#[serde(rename = "xml")]
XML,
#[serde(rename = "zip")]
ZIP,
#[serde(rename = "7z")]
SevenZ,
#[serde(rename = "none")]
None
}
#[derive(Debug,Clone, Serialize, Deserialize)]
pub struct Request {
#[serde(rename="version")]
version: String,
#[serde(rename="uri")]
pub uri: String,
#[serde(rename="sent")]
pub sent: DateTime<Utc>,
#[serde(rename="agent")]
pub agent: String,
#[serde(rename="method")]
pub method: Method,
#[serde(rename="lang")]
pub language: String,
#[serde(rename="contentType")]
pub content_type: ContentType,
#[serde(rename="content")]
pub content: Vec<u8>,
}
impl Request {
pub fn create(method: Method, uri: String, agent: String) -> Request {
Request {
version: ADTP_VERSION.to_string(),
uri,
sent: Utc::now(),
agent,
language: "none".to_string(),
method,
content_type: ContentType::None,
content: vec![],
}
}
pub fn with_time(mut self, sent: DateTime<Utc>) -> Request {
self.sent = sent;
self
}
pub fn with_language(mut self, language: String) -> Request {
self.language = language;
self
}
pub fn with_content(mut self, content_type: ContentType, content: Vec<u8>) -> Request {
self.content_type = content_type;
self.content = content;
self
}
pub fn with_content_string(mut self, content_type: ContentType, content: String) -> Request {
self.content_type = content_type;
self.content = content.into_bytes();
self
}
pub fn build(self) -> String {
serde_json::to_string(&self).unwrap()
}
}
impl TryFrom<String> for Request {
type Error = String;
fn try_from(value: String) -> Result<Self, Self::Error> {
match serde_json::from_str(&value) {
Ok(r) => Ok(r),
Err(e) => Err(format!("Failed to parse JSON: {}", e)),
}
}
}
impl TryFrom<Vec<u8>> for Request {
type Error = String;
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
match String::from_utf8(value) {
Ok(r) => match serde_json::from_str(r.as_str()) {
Ok(r) => Ok(r),
Err(e) => Err(format!("Failed to parse JSON: {}", e)),
},
Err(e) => Err(format!("Failed to parse JSON: {}", e)),
}
}
}
impl Display for Request {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", serde_json::to_string(&self).unwrap())
}
}
#[derive(Debug,Clone, Serialize, Deserialize)]
pub enum Status {
#[serde(rename="switch-protocols")]
SwitchProtocols, #[serde(rename="ok")]
Ok, #[serde(rename="pending")]
Pending, #[serde(rename="redirect")]
Redirect, #[serde(rename="denied")]
Denied, #[serde(rename="bad-request")]
BadRequest, #[serde(rename="unauthorized")]
Unauthorized, #[serde(rename="not-found")]
NotFound, #[serde(rename="too-many-requests")]
TooManyRequests, #[serde(rename="internal-error")]
InternalError, }
#[derive(Debug,Clone, Serialize, Deserialize)]
pub struct Response {
#[serde(rename="version")]
version: String,
#[serde(rename="status")]
pub status: Status,
#[serde(rename="sent")]
pub sent: DateTime<Utc>,
#[serde(rename="agent")]
pub agent: String,
#[serde(rename="language")]
pub language: String,
#[serde(rename="contentType")]
pub content_type: ContentType,
#[serde(rename="content")]
pub content: Vec<u8>,
}
impl Response {
pub fn create(status: Status, agent: String) -> Response {
Response {
version: ADTP_VERSION.to_string(),
status,
sent: Utc::now(),
agent,
language: "none".to_string(),
content_type: ContentType::None,
content: vec![],
}
}
pub fn with_time(mut self, sent: DateTime<Utc>) -> Response {
self.sent = sent;
self
}
pub fn with_language(mut self, language: String) -> Response {
self.language = language;
self
}
pub fn with_content(mut self, content_type: ContentType, content: Vec<u8>) -> Response {
self.content_type = content_type;
self.content = content;
self
}
pub fn with_content_string(mut self, content_type: ContentType, content: String) -> Response {
self.content_type = content_type;
self.content = content.into_bytes();
self
}
pub fn build(self) -> String {
serde_json::to_string(&self).unwrap()
}
}
impl TryFrom<String> for Response {
type Error = String;
fn try_from(value: String) -> Result<Self, Self::Error> {
match serde_json::from_str(&value) {
Ok(r) => Ok(r),
Err(e) => Err(format!("Failed to parse JSON: {}", e)),
}
}
}
impl TryFrom<Vec<u8>> for Response {
type Error = String;
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
match String::from_utf8(value) {
Ok(r) => match serde_json::from_str(r.as_str()) {
Ok(r) => Ok(r),
Err(e) => Err(format!("Failed to parse JSON: {}", e)),
},
Err(e) => Err(format!("Failed to parse JSON: {}", e)),
}
}
}
impl Display for Response {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", serde_json::to_string(&self).unwrap())
}
}