diff --git a/src/bin.rs b/src/bin.rs index aecb946a..41090e1b 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -22,6 +22,9 @@ pub mod project; pub mod pathext; pub mod vfs; pub mod vfs_watch; +pub mod rbx; +pub mod plugin; +pub mod plugins; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; diff --git a/src/plugin.rs b/src/plugin.rs new file mode 100644 index 00000000..1d03d326 --- /dev/null +++ b/src/plugin.rs @@ -0,0 +1,11 @@ +use rbx::RbxItem; +use vfs::VfsItem; + +pub enum PluginResult { + Value(Option), + Pass, +} + +pub trait Plugin { + fn transform(item: &VfsItem) -> PluginResult; +} diff --git a/src/plugins/default_plugin.rs b/src/plugins/default_plugin.rs new file mode 100644 index 00000000..b5beeca6 --- /dev/null +++ b/src/plugins/default_plugin.rs @@ -0,0 +1,49 @@ +use std::collections::HashMap; + +use plugin::{Plugin, PluginResult}; +use rbx::{RbxItem, RbxValue}; +use vfs::VfsItem; + +pub struct DefaultPlugin; + +impl Plugin for DefaultPlugin { + fn transform(item: &VfsItem) -> PluginResult { + match item { + &VfsItem::File { ref contents, ref name } => { + let mut properties = HashMap::new(); + + properties.insert("Value".to_string(), RbxValue::String { + value: contents.clone(), + }); + + PluginResult::Value(Some(RbxItem { + name: name.clone(), + class_name: "StringValue".to_string(), + children: Vec::new(), + properties, + })) + }, + &VfsItem::Dir { ref children, ref name } => { + // TODO: call back into plugin list and transform there instead + + let mut rbx_children = Vec::new(); + + for (_, child_item) in children { + match Self::transform(child_item) { + PluginResult::Value(Some(rbx_item)) => { + rbx_children.push(rbx_item); + }, + _ => {}, + } + } + + PluginResult::Value(Some(RbxItem { + name: name.clone(), + class_name: "Folder".to_string(), + children: rbx_children, + properties: HashMap::new(), + })) + }, + } + } +} diff --git a/src/plugins/mod.rs b/src/plugins/mod.rs new file mode 100644 index 00000000..c3b68bad --- /dev/null +++ b/src/plugins/mod.rs @@ -0,0 +1,3 @@ +mod default_plugin; + +pub use self::default_plugin::*; diff --git a/src/rbx.rs b/src/rbx.rs new file mode 100644 index 00000000..043dc3b6 --- /dev/null +++ b/src/rbx.rs @@ -0,0 +1,18 @@ +use std::collections::HashMap; + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct RbxItem { + pub name: String, + pub class_name: String, + pub children: Vec, + pub properties: HashMap, +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase", tag = "type")] +pub enum RbxValue { + String { + value: String, + }, +} diff --git a/src/vfs.rs b/src/vfs.rs index 44b9165f..81fb9c04 100644 --- a/src/vfs.rs +++ b/src/vfs.rs @@ -37,8 +37,8 @@ pub struct VfsChange { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase", tag = "type")] pub enum VfsItem { - File { contents: String }, - Dir { children: HashMap }, + File { name: String, contents: String }, + Dir { name: String, children: HashMap }, } impl Vfs { @@ -78,6 +78,7 @@ impl Vfs { } fn read_dir>(&self, path: P) -> Result { + let path = path.as_ref(); let reader = match fs::read_dir(path) { Ok(v) => v, Err(_) => return Err(()), @@ -104,11 +105,13 @@ impl Vfs { } Ok(VfsItem::Dir { + name: path.file_name().unwrap().to_string_lossy().into_owned(), children, }) } fn read_file>(&self, path: P) -> Result { + let path = path.as_ref(); let mut file = match File::open(path) { Ok(v) => v, Err(_) => return Err(()), @@ -122,6 +125,7 @@ impl Vfs { } Ok(VfsItem::File { + name: path.file_name().unwrap().to_string_lossy().into_owned(), contents, }) } diff --git a/src/web.rs b/src/web.rs index 4a8aaebe..670b0f0c 100644 --- a/src/web.rs +++ b/src/web.rs @@ -11,94 +11,12 @@ use regex::Regex; use core::Config; use project::Project; use vfs::{Vfs, VfsChange, VfsItem}; +use rbx::{RbxItem, RbxValue}; +use plugin::{Plugin, PluginResult}; +use plugins::DefaultPlugin; static MAX_BODY_SIZE: usize = 25 * 1024 * 1025; // 25 MiB -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -struct RbxItem { - name: String, - class_name: String, - children: Vec, - properties: HashMap, -} - -impl RbxItem { - pub fn from_vfs_item(file_name: &String, item: &VfsItem) -> RbxItem { - lazy_static! { - static ref PT_MODULE: Regex = Regex::new(r"^(.*?)\.lua$").unwrap(); - } - - match item { - &VfsItem::File { ref contents } => { - let mut properties = HashMap::new(); - - properties.insert("Source".to_string(), RbxValue::String { - value: contents.clone() - }); - - let rbx_name = { - if let Some(captures) = PT_MODULE.captures(file_name) { - captures.get(1).unwrap().as_str().to_string() - } else { - file_name.clone() - } - }; - - RbxItem { - name: rbx_name, - class_name: "ModuleScript".to_string(), - children: Vec::new(), - properties, - } - }, - &VfsItem::Dir { ref children } => { - let init = children.get(&"init.lua".to_string()); - - if let Some(init) = init { - let mut rbx_children = Vec::new(); - - for (name, child_item) in children { - if name != "init.lua" { - rbx_children.push(RbxItem::from_vfs_item(&name, &child_item)); - } - } - - let init_rbx = RbxItem::from_vfs_item(&"init.lua".to_string(), &init); - - RbxItem { - name: file_name.clone(), - class_name: init_rbx.class_name, - children: rbx_children, - properties: init_rbx.properties, - } - } else { - let mut rbx_children = Vec::new(); - - for (name, child_item) in children { - rbx_children.push(RbxItem::from_vfs_item(&name, &child_item)); - } - - RbxItem { - name: file_name.clone(), - class_name: "Folder".to_string(), - children: rbx_children, - properties: HashMap::new(), - } - } - }, - } - } -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase", tag = "type")] -enum RbxValue { - String { - value: String, - }, -} - #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] struct ServerInfo<'a> { @@ -243,7 +161,12 @@ pub fn start(config: Config, project: Project, vfs: Arc>) { .iter() .map(|item| { match *item { - Some(ref item) => Some(RbxItem::from_vfs_item(&"src".to_string(), item)), + Some(ref item) => { + match DefaultPlugin::transform(item) { + PluginResult::Value(rbx_item) => rbx_item, + _ => None, + } + }, None => None, } })