turbopack_core/module_graph/
module_batch.rs

1use std::fmt::Debug;
2
3use anyhow::Result;
4use serde::{Deserialize, Serialize};
5use turbo_rcstr::RcStr;
6use turbo_tasks::{
7    NonLocalValue, ReadRef, ResolvedVc, TaskInput, TryJoinIterExt, ValueToString, Vc,
8    trace::TraceRawVcs,
9};
10
11use crate::{
12    chunk::ChunkableModule, module::Module, module_graph::chunk_group_info::RoaringBitmapWrapper,
13};
14
15#[derive(
16    Debug,
17    Copy,
18    Clone,
19    Hash,
20    PartialEq,
21    Eq,
22    Serialize,
23    Deserialize,
24    TraceRawVcs,
25    NonLocalValue,
26    TaskInput,
27)]
28pub enum ModuleOrBatch {
29    Module(ResolvedVc<Box<dyn Module>>),
30    Batch(ResolvedVc<ModuleBatch>),
31    None(usize),
32}
33
34#[derive(
35    Debug,
36    Copy,
37    Clone,
38    Hash,
39    PartialEq,
40    Eq,
41    Serialize,
42    Deserialize,
43    TraceRawVcs,
44    NonLocalValue,
45    TaskInput,
46)]
47pub enum ChunkableModuleOrBatch {
48    Module(ResolvedVc<Box<dyn ChunkableModule>>),
49    Batch(ResolvedVc<ModuleBatch>),
50    None(usize),
51}
52
53impl ChunkableModuleOrBatch {
54    pub fn from_module_or_batch(module_or_batch: ModuleOrBatch) -> Option<Self> {
55        match module_or_batch {
56            ModuleOrBatch::Module(module) => ResolvedVc::try_downcast(module).map(Self::Module),
57            ModuleOrBatch::Batch(batch) => Some(Self::Batch(batch)),
58            ModuleOrBatch::None(i) => Some(Self::None(i)),
59        }
60    }
61
62    pub async fn ident_strings(self) -> Result<IdentStrings> {
63        Ok(match self {
64            ChunkableModuleOrBatch::Module(module) => {
65                IdentStrings::Single(module.ident().to_string().await?)
66            }
67            ChunkableModuleOrBatch::Batch(batch) => {
68                IdentStrings::Multiple(batch.ident_strings().await?)
69            }
70            ChunkableModuleOrBatch::None(_) => IdentStrings::None,
71        })
72    }
73}
74
75impl From<ChunkableModuleOrBatch> for ModuleOrBatch {
76    fn from(chunkable_module_or_batch: ChunkableModuleOrBatch) -> Self {
77        match chunkable_module_or_batch {
78            ChunkableModuleOrBatch::Module(module) => Self::Module(ResolvedVc::upcast(module)),
79            ChunkableModuleOrBatch::Batch(batch) => Self::Batch(batch),
80            ChunkableModuleOrBatch::None(i) => Self::None(i),
81        }
82    }
83}
84
85pub enum IdentStrings {
86    None,
87    Single(ReadRef<RcStr>),
88    Multiple(ReadRef<Vec<RcStr>>),
89}
90
91impl Debug for IdentStrings {
92    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93        match self {
94            IdentStrings::None => write!(f, "None"),
95            IdentStrings::Single(ident) => ident.fmt(f),
96            IdentStrings::Multiple(idents) => idents.fmt(f),
97        }
98    }
99}
100
101#[turbo_tasks::value]
102pub struct ModuleBatch {
103    pub modules: Vec<ResolvedVc<Box<dyn ChunkableModule>>>,
104    pub chunk_groups: Option<RoaringBitmapWrapper>,
105}
106
107#[turbo_tasks::value_impl]
108impl ModuleBatch {
109    #[turbo_tasks::function]
110    pub fn new(
111        modules: Vec<ResolvedVc<Box<dyn ChunkableModule>>>,
112        chunk_groups: Option<RoaringBitmapWrapper>,
113    ) -> Vc<Self> {
114        Self {
115            modules,
116            chunk_groups,
117        }
118        .cell()
119    }
120
121    #[turbo_tasks::function]
122    pub async fn ident_strings(&self) -> Result<Vc<Vec<RcStr>>> {
123        Ok(Vc::cell(
124            self.modules
125                .iter()
126                .map(|module| module.ident().to_string().owned())
127                .try_join()
128                .await?,
129        ))
130    }
131}
132
133#[turbo_tasks::value]
134pub struct ModuleBatchGroup {
135    pub items: Vec<ModuleOrBatch>,
136    pub chunk_groups: RoaringBitmapWrapper,
137}
138
139#[turbo_tasks::value_impl]
140impl ModuleBatchGroup {
141    #[turbo_tasks::function]
142    pub fn new(items: Vec<ModuleOrBatch>, chunk_groups: RoaringBitmapWrapper) -> Vc<Self> {
143        Self {
144            items,
145            chunk_groups,
146        }
147        .cell()
148    }
149}
150
151#[turbo_tasks::value]
152pub struct ChunkableModuleBatchGroup {
153    pub items: Vec<ChunkableModuleOrBatch>,
154    pub chunk_groups: RoaringBitmapWrapper,
155}
156
157#[turbo_tasks::value_impl]
158impl ChunkableModuleBatchGroup {
159    #[turbo_tasks::function]
160    pub async fn from_module_batch_group(batch_group: Vc<ModuleBatchGroup>) -> Result<Vc<Self>> {
161        let batch_group = batch_group.await?;
162        let items = batch_group
163            .items
164            .iter()
165            .filter_map(|batch| match *batch {
166                ModuleOrBatch::Module(module) => {
167                    ResolvedVc::try_downcast(module).map(ChunkableModuleOrBatch::Module)
168                }
169                ModuleOrBatch::Batch(batch) => Some(ChunkableModuleOrBatch::Batch(batch)),
170                ModuleOrBatch::None(_) => None,
171            })
172            .collect();
173        Ok(Self {
174            items,
175            chunk_groups: batch_group.chunk_groups.clone(),
176        }
177        .cell())
178    }
179}