webpack_stats/v5/
chunk.rs

1/*
2 * Copyright [2022] [Kevin Velasco]
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use crate::common::SizeBytes;
18use crate::v5::module::Modules;
19use crate::v5::reason::Reasons;
20use serde::Deserialize;
21use std::borrow::Cow;
22
23use crate::chunk::{
24    ChunkChild, ChunkChildren, ChunkInitial, ChunkModules, ChunkParentOrSibling, Files,
25};
26use crate::common::chunk::{ChunkId, ChunkName};
27use crate::common::import::SourceFilePath;
28use crate::common::module::{ModuleId, ModuleIdentifier, RelativeModulePath};
29use meshed::prelude::*;
30
31#[derive(Debug, Default, Deserialize)]
32#[serde(transparent)]
33pub struct Chunks<'a> {
34    #[serde(borrow)]
35    pub chunks: Vec<Chunk<'a>>,
36}
37
38impl<'a> crate::common::chunk::Chunks<Chunk<'a>> for Chunks<'a> {}
39
40impl<'a> Query<ChunkId, Chunk<'a>> for Chunks<'a> {
41    fn query(&self, identifier: &ChunkId) -> Option<&Chunk<'a>> {
42        self.chunks
43            .iter()
44            .find(|chunk| &chunk.get_id() == identifier)
45    }
46
47    fn all(&self) -> Vec<&Chunk<'a>> {
48        self.chunks.iter().collect()
49    }
50}
51
52#[derive(Deserialize, Debug)]
53#[serde(rename_all = "camelCase")]
54pub struct Chunk<'a> {
55    pub id: ChunkId,
56    pub entry: bool,
57    pub initial: bool,
58    #[serde(borrow)]
59    pub modules: Modules<'a>,
60    pub files: Vec<SourceFilePath<'a>>,
61    #[serde(borrow)]
62    pub names: Vec<ChunkName<'a>>,
63    #[serde(default)]
64    pub origins: Vec<Origin<'a>>,
65    pub parents: Vec<ChunkId>,
66    pub siblings: Vec<ChunkId>,
67    pub children: Vec<ChunkId>,
68    pub rendered: bool,
69    pub size: SizeBytes,
70}
71
72impl<'a> ExtractData<ChunkId> for Chunk<'a> {
73    fn extract_data(&self) -> ChunkId {
74        self.id
75    }
76}
77
78impl<'a> ExtractData<ChunkChildren> for Chunk<'a> {
79    fn extract_data(&self) -> ChunkChildren {
80        ChunkChildren(self.children.clone())
81    }
82}
83
84impl<'a> ExtractData<SizeBytes> for Chunk<'a> {
85    fn extract_data(&self) -> SizeBytes {
86        self.size
87    }
88}
89
90impl<'a> ExtractData<ChunkModules> for Chunk<'a> {
91    fn extract_data(&self) -> ChunkModules {
92        self.modules
93            .modules
94            .iter()
95            .map(|module| module.identifier.clone())
96            .collect()
97    }
98}
99
100impl<'a> Label for Chunk<'a> {
101    type Label = ChunkId;
102
103    fn label(&self) -> Self::Label {
104        self.id
105    }
106}
107
108impl<'a> ExtractData<ChunkInitial> for Chunk<'a> {
109    fn extract_data(&self) -> ChunkInitial {
110        ChunkInitial(self.initial)
111    }
112}
113
114impl<'a> ExtractData<Files> for Chunk<'a> {
115    fn extract_data(&self) -> Files {
116        Files(
117            self.files
118                .iter()
119                .map(|f| f.0.to_string_lossy().to_string())
120                .collect(),
121        )
122    }
123}
124
125impl<'a> crate::common::chunk::Chunk for Chunk<'a> {}
126
127impl<'a> Identifiable<ChunkId> for Chunk<'a> {
128    fn get_id(&self) -> ChunkId {
129        self.id
130    }
131}
132
133impl<'a> Edges<ChunkId, ChunkParentOrSibling> for Chunk<'a> {
134    fn next_edge(
135        &self,
136        previous_edge_index: Option<usize>,
137    ) -> Option<Edge<ChunkId, ChunkParentOrSibling>> {
138        let next_idx = previous_edge_index.map(|e| e + 1).unwrap_or_default();
139        let data = if next_idx < self.siblings.len() {
140            self.siblings.get(next_idx).cloned()?
141        } else {
142            self.parents.get(next_idx - self.siblings.len()).cloned()?
143        };
144
145        Some(Edge::new(
146            self.get_id(),
147            data,
148            next_idx,
149            ChunkParentOrSibling,
150        ))
151    }
152}
153
154impl<'a> Edges<ChunkId, ChunkChild> for Chunk<'a> {
155    fn next_edge(&self, previous_edge_index: Option<usize>) -> Option<Edge<ChunkId, ChunkChild>> {
156        let next_idx = previous_edge_index.map(|e| e + 1).unwrap_or_default();
157        let data = self.children.get(next_idx).cloned()?;
158
159        Some(Edge::new(self.get_id(), data, next_idx, ChunkChild))
160    }
161}
162
163#[derive(Deserialize, Debug)]
164#[serde(rename_all = "camelCase")]
165pub struct Origin<'a> {
166    #[serde(borrow)]
167    pub loc: Cow<'a, str>,
168    pub module_identifier: ModuleIdentifier,
169    #[serde(default)]
170    pub module_id: Option<ModuleId>,
171    pub module_name: RelativeModulePath<'a>,
172    #[serde(default)]
173    pub reasons: Reasons<'a>,
174}