1#[cfg(feature = "default-themes")]
16use crate::highlighting::ThemeSet;
17#[cfg(feature = "default-syntaxes")]
18use crate::parsing::SyntaxSet;
19#[cfg(feature = "dump-load")]
20use bincode::deserialize_from;
21#[cfg(feature = "dump-create")]
22use bincode::serialize_into;
23#[cfg(feature = "dump-load")]
24use flate2::bufread::ZlibDecoder;
25#[cfg(feature = "dump-create")]
26use flate2::write::ZlibEncoder;
27#[cfg(feature = "dump-create")]
28use flate2::Compression;
29#[cfg(feature = "dump-load")]
30use serde::de::DeserializeOwned;
31#[cfg(feature = "dump-create")]
32use serde::ser::Serialize;
33use std::fs::File;
34#[cfg(feature = "dump-load")]
35use std::io::BufRead;
36#[cfg(feature = "dump-create")]
37use std::io::{BufWriter, Write};
38use std::path::Path;
39
40#[derive(Debug, thiserror::Error)]
42#[non_exhaustive]
43pub enum DumpError {
44 #[error("IO error: {0}")]
46 Io(#[from] std::io::Error),
47 #[error("Serialization error: {0}")]
49 Serialize(#[source] Box<dyn std::error::Error + Send + Sync>),
50}
51
52#[cfg(feature = "dump-create")]
56pub fn dump_to_writer<T: Serialize, W: Write>(to_dump: &T, output: W) -> Result<(), DumpError> {
57 serialize_to_writer_impl(to_dump, output, true)
58}
59
60#[cfg(feature = "dump-create")]
64pub fn dump_binary<T: Serialize>(o: &T) -> Vec<u8> {
65 let mut v = Vec::new();
66 dump_to_writer(o, &mut v).unwrap();
67 v
68}
69
70#[cfg(feature = "dump-create")]
77pub fn dump_to_file<T: Serialize, P: AsRef<Path>>(o: &T, path: P) -> Result<(), DumpError> {
78 let out = BufWriter::new(File::create(path)?);
79 dump_to_writer(o, out)
80}
81
82#[cfg(feature = "dump-load")]
84pub fn from_reader<T: DeserializeOwned, R: BufRead>(input: R) -> Result<T, DumpError> {
85 deserialize_from_reader_impl(input, true)
86}
87
88#[cfg(feature = "dump-load")]
92pub fn from_binary<T: DeserializeOwned>(v: &[u8]) -> T {
93 from_reader(v).unwrap()
94}
95
96#[cfg(feature = "dump-load")]
98pub fn from_dump_file<T: DeserializeOwned, P: AsRef<Path>>(path: P) -> Result<T, DumpError> {
99 let contents = std::fs::read(path)?;
100 from_reader(&contents[..])
101}
102
103#[cfg(feature = "dump-create")]
108pub fn dump_to_uncompressed_file<T: Serialize, P: AsRef<Path>>(
109 o: &T,
110 path: P,
111) -> Result<(), DumpError> {
112 let out = BufWriter::new(File::create(path)?);
113 serialize_to_writer_impl(o, out, false)
114}
115
116#[cfg(feature = "dump-load")]
119pub fn from_uncompressed_dump_file<T: DeserializeOwned, P: AsRef<Path>>(
120 path: P,
121) -> Result<T, DumpError> {
122 let contents = std::fs::read(path)?;
123 deserialize_from_reader_impl(&contents[..], false)
124}
125
126#[cfg(feature = "dump-load")]
130pub fn from_uncompressed_data<T: DeserializeOwned>(v: &[u8]) -> Result<T, DumpError> {
131 deserialize_from_reader_impl(v, false)
132}
133
134#[cfg(feature = "dump-create")]
136fn serialize_to_writer_impl<T: Serialize, W: Write>(
137 to_dump: &T,
138 output: W,
139 use_compression: bool,
140) -> Result<(), DumpError> {
141 if use_compression {
142 let mut encoder = std::io::BufWriter::new(ZlibEncoder::new(output, Compression::best()));
143 serialize_into(&mut encoder, to_dump).map_err(|e| DumpError::Serialize(Box::new(e)))
144 } else {
145 serialize_into(output, to_dump).map_err(|e| DumpError::Serialize(Box::new(e)))
146 }
147}
148
149#[cfg(feature = "dump-load")]
151fn deserialize_from_reader_impl<T: DeserializeOwned, R: BufRead>(
152 input: R,
153 use_compression: bool,
154) -> Result<T, DumpError> {
155 if use_compression {
156 let mut decoder = ZlibDecoder::new(input);
157 deserialize_from(&mut decoder).map_err(|e| DumpError::Serialize(Box::new(e)))
158 } else {
159 deserialize_from(input).map_err(|e| DumpError::Serialize(Box::new(e)))
160 }
161}
162
163#[cfg(feature = "default-syntaxes")]
164impl SyntaxSet {
165 pub fn load_defaults_nonewlines() -> SyntaxSet {
185 #[cfg(feature = "metadata")]
186 {
187 let mut ps: SyntaxSet =
188 from_uncompressed_data(include_bytes!("../assets/default_nonewlines.packdump"))
189 .unwrap();
190 let metadata = from_binary(include_bytes!("../assets/default_metadata.packdump"));
191 ps.metadata = metadata;
192 ps
193 }
194 #[cfg(not(feature = "metadata"))]
195 {
196 from_uncompressed_data(include_bytes!("../assets/default_nonewlines.packdump")).unwrap()
197 }
198 }
199
200 pub fn load_defaults_newlines() -> SyntaxSet {
207 #[cfg(feature = "metadata")]
208 {
209 let mut ps: SyntaxSet =
210 from_uncompressed_data(include_bytes!("../assets/default_newlines.packdump"))
211 .unwrap();
212 let metadata = from_binary(include_bytes!("../assets/default_metadata.packdump"));
213 ps.metadata = metadata;
214 ps
215 }
216 #[cfg(not(feature = "metadata"))]
217 {
218 from_uncompressed_data(include_bytes!("../assets/default_newlines.packdump")).unwrap()
219 }
220 }
221}
222
223#[cfg(feature = "default-themes")]
224impl ThemeSet {
225 pub fn load_defaults() -> ThemeSet {
232 from_binary(include_bytes!("../assets/default.themedump"))
233 }
234}
235
236#[cfg(test)]
237mod tests {
238 #[cfg(all(
239 feature = "yaml-load",
240 feature = "dump-create",
241 feature = "dump-load",
242 feature = "parsing"
243 ))]
244 #[test]
245 fn can_dump_and_load() {
246 use super::*;
247 use crate::utils::testdata;
248
249 let ss = &*testdata::PACKAGES_SYN_SET;
250
251 let bin = dump_binary(&ss);
252 println!("{:?}", bin.len());
253 let ss2: SyntaxSet = from_binary(&bin[..]);
254 assert_eq!(ss.syntaxes().len(), ss2.syntaxes().len());
255 }
256
257 #[cfg(all(feature = "yaml-load", feature = "dump-create", feature = "dump-load"))]
258 #[test]
259 fn dump_is_deterministic() {
260 use super::*;
261 use crate::parsing::SyntaxSetBuilder;
262 use crate::utils::testdata;
263
264 let ss1 = &*testdata::PACKAGES_SYN_SET;
265 let bin1 = dump_binary(&ss1);
266
267 let mut builder2 = SyntaxSetBuilder::new();
268 builder2
269 .add_from_folder("testdata/Packages", false)
270 .unwrap();
271 let ss2 = builder2.build();
272 let bin2 = dump_binary(&ss2);
273 assert_eq!(bin1.len(), bin2.len());
276 assert_eq!(bin1, bin2);
277 }
278
279 #[cfg(feature = "default-themes")]
280 #[test]
281 fn has_default_themes() {
282 use crate::highlighting::ThemeSet;
283 let themes = ThemeSet::load_defaults();
284 assert!(themes.themes.len() > 4);
285 }
286}