use crate::idl;
use crate::ids;
use convert_case::{Case, Casing};
use serde::{Deserialize, Serialize};
use std::{io::Write, path::Path};
pub mod protocol_test;
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ClientType {
pub client_name: String,
pub server_name: String,
}
#[derive(Debug, Deserialize, Serialize)]
pub enum BuildType {
Release,
Debug,
}
#[derive(Debug, Deserialize, Serialize)]
pub enum ServerArg {
Run,
Build,
Generate,
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ServerType {
pub server_name: String,
pub input_path: String,
pub build_type: BuildType,
pub args: ServerArg,
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DataType {
pub server_name: String,
pub input_path: String,
}
#[derive(Debug, Deserialize, Serialize)]
pub enum RequestType {
Client(ClientType),
Server(ServerType),
Data(DataType),
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LibraryItem {
pub nodes: Vec<idl::nodes::IdlNode>,
pub hash: Box<[u8]>,
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LanguageRequest {
pub libraries: Vec<LibraryItem>,
pub ids_nodes: Vec<ids::nodes::IdsNode>,
pub request_type: RequestType,
}
#[derive(Debug, Deserialize, Serialize)]
pub enum ResponseType {
Generated(Vec<StorageItem>),
Undefined(String),
}
#[derive(Debug, Deserialize, Serialize)]
pub enum StorageItem {
Source {
name: String,
txt: String,
},
Folder {
name: String,
items: Vec<StorageItem>,
},
BinarySource {
name: String,
data: String,
},
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LanguageResponse {
pub response_type: ResponseType,
pub response_messages: Vec<String>,
}
pub trait IdlGen {
fn send_request(&self, request: LanguageRequest) -> anyhow::Result<LanguageResponse>;
}
impl StorageItem {
pub fn write_items(&self, path: &Path, is_merged: bool) -> anyhow::Result<()> {
match self {
Self::Source { name, txt } => {
let mut file = std::fs::OpenOptions::new()
.write(true)
.truncate(true)
.create(true)
.open(path.join(name.as_str()))?;
file.write_all(txt.as_bytes())?;
}
Self::Folder { name, items } => {
let new_path = path.join(&name);
if !is_merged {
let _ = std::fs::remove_dir_all(&new_path);
}
std::fs::create_dir_all(&new_path)?;
for item in items {
item.write_items(&new_path, is_merged)?;
}
}
Self::BinarySource { name, data } => {
let mut file = std::fs::OpenOptions::new()
.write(true)
.truncate(true)
.create(true)
.open(path.join(name.as_str()))?;
file.write_all(&base64::decode(data)?)?;
}
}
Ok(())
}
}
pub fn create_new_module(name: &str) -> StorageItem {
let mut result = vec![];
result.push(StorageItem::Folder {
name: ".idl".to_owned(),
items: vec![],
});
result.push(StorageItem::Source {
name: ".gitignore".to_owned(),
txt: "".to_owned(),
});
result.push(StorageItem::Source {
name: format!("{}.ids", name.to_case(Case::Snake)),
txt: format!(
r#"package {} {{
idl: 0,
version: 1,
}}
server Main {{ }}
client Main {{ }}
"#,
name.to_case(Case::Camel),
),
});
result.push(StorageItem::Source {
name: format!("{}.idl", name.to_case(Case::Snake)),
txt: format!(
r#"library {};
interface Service {{
hello: (value: string) -> string,
}}
"#,
name.to_case(Case::Snake),
),
});
return StorageItem::Folder {
name: name.to_case(Case::Snake),
items: result,
};
}