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