rust 我如何在构建时获得文件总数,然后将其传递给Yew中的Web程序集?

hl0ma9xz  于 2023-03-18  发布在  其他
关注(0)|答案(1)|浏览(105)

我目前正在构建一个图像轮播,我想计算一个只能在操作系统级别访问的目录的内容,并将结果传递给Yew中的一个Web组件模块内的静态散列表。
这里有一个use_reducer和一个Context,我希望在其中使用默认状态保存文件计数。

use std::{cmp::max, collections::HashMap, fs, rc::Rc};
use yew::prelude::*;

extern crate web_sys;

// A macro to provide `println!(..)`-style syntax for `console.log` logging.
macro_rules! log {
    ( $( $t:tt )* ) => {
        web_sys::console::log_1(&format!( $( $t )* ).into());
    }
}

pub enum CarouselAction {
    Prev,
    Next,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct CarouselState {
    chapter_state: HashMap<i32, i32>,
    pub page: i32,
    pub chapter: i32,
}

pub type CarouselContext = UseReducerHandle<CarouselState>;

impl Default for CarouselState {
    fn default() -> Self {
        let dir = "./assets/carousel/op";
        let total_chapters = fs::read_dir(dir)
            .unwrap()
            .filter(|entry| entry.as_ref().unwrap().metadata().unwrap().is_file())
            .count();
        log!("TOTAL CHAPTERS {}", total_chapters);
        Self {
            chapter_state: HashMap::new(),
            page: 1,
            chapter: 1043,
        }
    }
}

impl Reducible for CarouselState {
    // Reducer Action Type
    type Action = CarouselAction;

    fn reduce(self: Rc<Self>, action: Self::Action) -> Rc<Self> {
        match action {
            CarouselAction::Prev => Self {
                page: max(self.page - 1, 1),
                chapter: self.chapter,
                chapter_state: self.chapter_state.to_owned(),
            }
            .into(),
            CarouselAction::Next => {
                log!("self.page {}", self.page);
                Self {
                    page: self.page + 1,
                    chapter: self.chapter,
                    chapter_state: self.chapter_state.to_owned(),
                }
                .into()
            }
        }
    }
}

#[derive(PartialEq, Debug, Properties)]
pub struct CarouselContextProps {
    #[prop_or_default]
    pub children: Children,
}

#[function_component(CarouselContextProvider)]
pub fn carousel_context_provider(props: &CarouselContextProps) -> Html {
    let state = use_reducer(CarouselState::default);
    html! {
        <ContextProvider<CarouselContext> context={state}>
            {props.children.clone()}
        </ContextProvider<CarouselContext>>
    }
}

pub fn use_carousel_context() -> impl Hook<Output = Option<UseReducerHandle<CarouselState>>> {
    use_context::<CarouselContext>()
}

有关代码为:

impl Default for CarouselState {
    fn default() -> Self {
        let dir = "./assets/carousel/op";
        let total_chapters = fs::read_dir(dir)
            .unwrap()
            .filter(|entry| entry.as_ref().unwrap().metadata().unwrap().is_file())
            .count();
        log!("TOTAL CHAPTERS {}", total_chapters);
        Self {
            chapter_state: HashMap::new(),
            page: 1,
            chapter: 1043,
        }
    }
}

我正在浏览器中运行文件系统,它是不可访问的,它返回了一个错误(很明显),我想在编译成wasm并将结果保存在chapter_state散列Map之前运行这段代码。
这可能吗?
我目前正在考虑使用一个单独的脚本来生成一个包含哈希Map结果的文件,然后将该文件包含在紫杉中。

gcuhipw9

gcuhipw91#

正如@cafce25所指出的,诀窍在于使用一个build.rs文件。
Yew无法“注入”JSON文件,因此我们通过编程创建了一个info.rs文件,其中包含来自输出的HashMap。
下面是build.rs(位于根目录中,在src之外)x1c 0d1x的内容
下面是我们的代码:

use std::{collections::HashMap, fs};

fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    let out_dir = "./src/";

    let mut chapter_state: HashMap<i16, i8> = HashMap::new();

    let dir_path = "./src/assets/manga/one_piece"; // replace with your directory path

    let manga_folders = fs::read_dir(dir_path).expect("Failed to read directory");

    for read in manga_folders {
        let entry = match read {
            Err(_) => continue,
            Ok(e) => e,
        };

        if !entry.path().is_dir() {
            continue;
        }

        if let Some(folder_name) = entry.path().file_name().and_then(|n| n.to_str()) {
            if let Ok(folder_num) = folder_name.parse::<i16>() {
                let count = fs::read_dir(entry.path())
                    .expect("Failed to read directory")
                    .count() as i8;

                chapter_state.insert(folder_num, count);
            }
        }
    }

    let mut sorted_manga_folders: Vec<(i16, i8)> = chapter_state.into_iter().collect();
    sorted_manga_folders.sort_by_key(|&(chapter, _)| -chapter);

    let mut chapter_concat: String = "[".to_owned();
    for (index, (chapter, page)) in sorted_manga_folders.iter().enumerate() {
        let comma_suffix = if index == sorted_manga_folders.len() - 1 {
            ""
        } else {
            ","
        };
        chapter_concat.push_str(&format!("({}, {}){}", chapter, page, comma_suffix));
    }

    chapter_concat.push_str("]");

    println!("cargo:warning={:?}", &chapter_concat);

    let info_rs = format!(
        "
        use std::collections::HashMap;
        pub fn get_chapters() -> HashMap<i16, i8> {{
        let chapter_state: HashMap<i16, i8> = HashMap::from({});
            chapter_state
        }}
    
    ",
        chapter_concat
    );

    let dest_path = format!("{}/info.rs", out_dir);
    fs::write(&dest_path, info_rs).unwrap();
}

我们在这里所做的(随时建议一个更好的方法)是:
1.构建一个类似于shape的JSON的HashMap:

{
  [chapter: number]: number;
}

1.读取目录的内容并填写散列表。
1.我们创建一个info.rs文件,它返回一个hashmap(元编程),产生如下结果:

use std::collections::HashMap;
        pub fn get_chapters() -> HashMap<i16, i8> {
        let chapter_state: HashMap<i16, i8> = HashMap::from([(1047, 20),(1046, 17),(1045, 20),(1044, 17),(1043, 17),(1042, 17)]);
            chapter_state
        }

相关问题