use tokio::try_join; use super::list::Params; use crate::prelude::*; #[derive(Serialize, Debug)] pub struct FolderStructure { #[serde(flatten)] folder_base: db::folder::FolderWithoutParentId, folders: Vec, files: Vec, } impl From for FolderStructure { fn from(value: db::folder::FolderWithoutParentId) -> Self { FolderStructure { folder_base: value, folders: Vec::new(), files: Vec::new(), } } } pub async fn structure( Query(params): Query, State(pool): State, claims: Claims, ) -> GeneralResult> { let folder_id = db::folder::process_id(params.folder_id, claims.user_id, &pool) .await .handle_internal("Error processing id")? .ok_or_else(GeneralError::item_not_found)?; let folder = db::folder::get_by_id(folder_id, &pool) .await .handle_internal("Error getting folder info")? .ok_or_else(GeneralError::item_not_found)?; let mut response: FolderStructure = folder.into(); let mut stack = vec![&mut response]; while let Some(folder) = stack.pop() { let (files, folders) = try_join!( db::file::get_files(folder.folder_base.folder_id, &pool).try_collect(), db::folder::get_folders(folder.folder_base.folder_id, claims.user_id, &pool) .map_ok(Into::into) .try_collect() ) .handle_internal("Error getting folder contents")?; folder.folders = folders; folder.files = files; stack.extend(folder.folders.iter_mut()); } Ok(Json(response)) }