1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5#[non_exhaustive]
6pub enum Syntax {
7 Portable,
9 Node,
11 Python,
13 Compose,
15 Docker,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
21#[non_exhaustive]
22pub enum InlineComments {
23 Whitespace,
25 Space,
27 AnyHash,
29 Python,
31 None,
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
37pub struct DoubleEscapes(u16);
38impl DoubleEscapes {
39 pub const NONE: Self = Self(0);
41 pub const LF: Self = Self(1);
43 pub const CR: Self = Self(1 << 1);
45 pub const TAB: Self = Self(1 << 2);
47 pub const BACKSLASH: Self = Self(1 << 3);
49 pub const DOUBLE_QUOTE: Self = Self(1 << 4);
51 pub const DOLLAR: Self = Self(1 << 5);
53 pub const SINGLE_QUOTE: Self = Self(1 << 6);
55 pub const BELL: Self = Self(1 << 7);
57 pub const BACKSPACE: Self = Self(1 << 8);
59 pub const FORM_FEED: Self = Self(1 << 9);
61 pub const VERTICAL_TAB: Self = Self(1 << 10);
63 pub const OCTAL: Self = Self(1 << 11);
65 pub const PORTABLE: Self = Self(0x3f);
67 pub const NODE: Self = Self(3);
69 pub const PYTHON: Self = Self(0x7df);
71 pub const COMPOSE: Self = Self(0xfbf);
73 #[must_use]
75 pub const fn union(self, other: Self) -> Self {
76 Self(self.0 | other.0)
77 }
78 #[must_use]
80 pub const fn contains(self, other: Self) -> bool {
81 self.0 & other.0 == other.0
82 }
83}
84
85#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
87#[non_exhaustive]
88pub enum UnknownEscapes {
89 Preserve,
91 Warn,
93 DropBackslash,
95 Error,
97}
98#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
100#[non_exhaustive]
101pub enum SingleEscapes {
102 None,
104 Quote,
106 QuoteAndBackslash,
108}
109#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
111#[non_exhaustive]
112pub enum ColonSeparator {
113 None,
115 Whitespace,
117 Any,
119}
120#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
122#[non_exhaustive]
123pub enum KeySyntax {
124 Posix,
126 Portable,
128 Unicode,
130 NonWhitespace,
132 Python,
134 Compose,
136 Docker,
138}
139#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
141#[non_exhaustive]
142pub enum BareKeys {
143 Preserve,
145 Ignore,
147 Empty,
149 Error,
151}
152#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
154#[non_exhaustive]
155pub enum LineBreaks {
156 Universal,
158 Lf,
160}
161#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
163#[non_exhaustive]
164pub enum BomPolicy {
165 Strip,
167 Keep,
169 Error,
171}
172#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
174#[non_exhaustive]
175pub enum Duplicates {
176 First,
178 Last,
180}
181#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
183#[non_exhaustive]
184pub enum QuotedTail {
185 Error,
187 Ignore,
189 Append,
191 LiteralFallback,
193 Skip,
195 NextStatement,
197}
198#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
200#[non_exhaustive]
201pub struct Multiline {
202 pub single: bool,
204 pub double: bool,
206 pub backtick: bool,
208}
209impl Multiline {
210 #[must_use]
212 pub const fn with_single(mut self, value: bool) -> Self {
213 self.single = value;
214 self
215 }
216 #[must_use]
218 pub const fn with_double(mut self, value: bool) -> Self {
219 self.double = value;
220 self
221 }
222 #[must_use]
224 pub const fn with_backtick(mut self, value: bool) -> Self {
225 self.backtick = value;
226 self
227 }
228}
229impl Multiline {
230 pub const ALL: Self = Self {
232 single: true,
233 double: true,
234 backtick: true,
235 };
236 pub const NONE: Self = Self {
238 single: false,
239 double: false,
240 backtick: false,
241 };
242}
243#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
245#[non_exhaustive]
246pub enum Whitespace {
247 Ascii,
249 Unicode,
251 EcmaScript,
253 Python,
255 Compose,
257}
258#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
260#[non_exhaustive]
261pub enum MalformedLines {
262 Error,
264 Ignore,
266}
267
268#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
270#[allow(clippy::struct_excessive_bools)]
272#[non_exhaustive]
273pub struct Dialect {
274 pub syntax: Syntax,
276 pub inline_comments: InlineComments,
278 pub double_escapes: DoubleEscapes,
280 pub unknown_escapes: UnknownEscapes,
282 pub single_escapes: SingleEscapes,
284 pub backticks: bool,
286 pub colon: ColonSeparator,
288 pub keys: KeySyntax,
290 pub bare_keys: BareKeys,
292 pub raw_values: bool,
294 pub line_breaks: LineBreaks,
296 pub bom: BomPolicy,
298 pub duplicates: Duplicates,
300 pub quoted_tail: QuotedTail,
302 pub multiline: Multiline,
304 pub whitespace: Whitespace,
306 pub export: bool,
308 pub quoted_keys: bool,
310 pub quoted_comments: bool,
312 pub normalize_newlines: bool,
314 pub malformed_lines: MalformedLines,
316 pub node_object_keys: bool,
318 pub line_byte_limit: Option<usize>,
320}
321impl Dialect {
322 pub const PORTABLE: Self = Self {
324 syntax: Syntax::Portable,
325 inline_comments: InlineComments::Whitespace,
326 double_escapes: DoubleEscapes::PORTABLE,
327 unknown_escapes: UnknownEscapes::Warn,
328 single_escapes: SingleEscapes::None,
329 backticks: false,
330 colon: ColonSeparator::None,
331 keys: KeySyntax::Portable,
332 bare_keys: BareKeys::Preserve,
333 raw_values: false,
334 line_breaks: LineBreaks::Universal,
335 bom: BomPolicy::Strip,
336 duplicates: Duplicates::Last,
337 quoted_tail: QuotedTail::Error,
338 multiline: Multiline::ALL,
339 whitespace: Whitespace::Ascii,
340 export: true,
341 quoted_keys: false,
342 quoted_comments: false,
343 normalize_newlines: false,
344 malformed_lines: MalformedLines::Error,
345 node_object_keys: false,
346 line_byte_limit: None,
347 };
348 pub const NODE_DOTENV: Self = Self {
350 syntax: Syntax::Node,
351 whitespace: Whitespace::EcmaScript,
352 inline_comments: InlineComments::AnyHash,
353 double_escapes: DoubleEscapes::NODE,
354 unknown_escapes: UnknownEscapes::Preserve,
355 backticks: true,
356 colon: ColonSeparator::Whitespace,
357 bare_keys: BareKeys::Ignore,
358 quoted_tail: QuotedTail::LiteralFallback,
359 quoted_comments: true,
360 normalize_newlines: true,
361 malformed_lines: MalformedLines::Ignore,
362 node_object_keys: true,
363 ..Self::PORTABLE
364 };
365 pub const PYTHON_DOTENV: Self = Self {
367 syntax: Syntax::Python,
368 whitespace: Whitespace::Python,
369 inline_comments: InlineComments::Python,
370 double_escapes: DoubleEscapes::PYTHON,
371 unknown_escapes: UnknownEscapes::Preserve,
372 single_escapes: SingleEscapes::QuoteAndBackslash,
373 keys: KeySyntax::Python,
374 quoted_keys: true,
375 quoted_comments: true,
376 ..Self::PORTABLE
377 };
378 pub const COMPOSE: Self = Self {
380 syntax: Syntax::Compose,
381 whitespace: Whitespace::Compose,
382 inline_comments: InlineComments::Space,
383 double_escapes: DoubleEscapes::COMPOSE,
384 unknown_escapes: UnknownEscapes::Preserve,
385 single_escapes: SingleEscapes::Quote,
386 colon: ColonSeparator::Any,
387 keys: KeySyntax::Compose,
388 bare_keys: BareKeys::Ignore,
389 line_breaks: LineBreaks::Lf,
390 quoted_tail: QuotedTail::NextStatement,
391 quoted_comments: true,
392 ..Self::PORTABLE
393 };
394 pub const DOCKER_RAW: Self = Self {
396 syntax: Syntax::Docker,
397 whitespace: Whitespace::Unicode,
398 inline_comments: InlineComments::None,
399 double_escapes: DoubleEscapes::NONE,
400 unknown_escapes: UnknownEscapes::Preserve,
401 keys: KeySyntax::Docker,
402 bare_keys: BareKeys::Ignore,
403 raw_values: true,
404 line_breaks: LineBreaks::Lf,
405 multiline: Multiline::NONE,
406 export: false,
407 line_byte_limit: Some(65_535),
408 ..Self::PORTABLE
409 };
410}
411impl Dialect {
412 #[must_use]
414 pub const fn with_syntax(mut self, syntax: Syntax) -> Self {
415 self.syntax = syntax;
416 self
417 }
418 #[must_use]
420 pub const fn with_inline_comments(mut self, value: InlineComments) -> Self {
421 self.inline_comments = value;
422 self
423 }
424 #[must_use]
426 pub const fn with_double_escapes(mut self, value: DoubleEscapes) -> Self {
427 self.double_escapes = value;
428 self
429 }
430 #[must_use]
432 pub const fn with_unknown_escapes(mut self, value: UnknownEscapes) -> Self {
433 self.unknown_escapes = value;
434 self
435 }
436 #[must_use]
438 pub const fn with_single_escapes(mut self, value: SingleEscapes) -> Self {
439 self.single_escapes = value;
440 self
441 }
442 #[must_use]
444 pub const fn with_backticks(mut self, value: bool) -> Self {
445 self.backticks = value;
446 self
447 }
448 #[must_use]
450 pub const fn with_colon(mut self, value: ColonSeparator) -> Self {
451 self.colon = value;
452 self
453 }
454 #[must_use]
456 pub const fn with_keys(mut self, value: KeySyntax) -> Self {
457 self.keys = value;
458 self
459 }
460 #[must_use]
462 pub const fn with_bare_keys(mut self, value: BareKeys) -> Self {
463 self.bare_keys = value;
464 self
465 }
466 #[must_use]
468 pub const fn with_raw_values(mut self, value: bool) -> Self {
469 self.raw_values = value;
470 self
471 }
472 #[must_use]
474 pub const fn with_line_breaks(mut self, value: LineBreaks) -> Self {
475 self.line_breaks = value;
476 self
477 }
478 #[must_use]
480 pub const fn with_bom(mut self, value: BomPolicy) -> Self {
481 self.bom = value;
482 self
483 }
484 #[must_use]
486 pub const fn with_duplicates(mut self, value: Duplicates) -> Self {
487 self.duplicates = value;
488 self
489 }
490 #[must_use]
492 pub const fn with_quoted_tail(mut self, value: QuotedTail) -> Self {
493 self.quoted_tail = value;
494 self
495 }
496 #[must_use]
498 pub const fn with_multiline(mut self, value: Multiline) -> Self {
499 self.multiline = value;
500 self
501 }
502 #[must_use]
504 pub const fn with_whitespace(mut self, value: Whitespace) -> Self {
505 self.whitespace = value;
506 self
507 }
508 #[must_use]
510 pub const fn with_export(mut self, value: bool) -> Self {
511 self.export = value;
512 self
513 }
514 #[must_use]
516 pub const fn with_quoted_keys(mut self, value: bool) -> Self {
517 self.quoted_keys = value;
518 self
519 }
520 #[must_use]
522 pub const fn with_quoted_comments(mut self, value: bool) -> Self {
523 self.quoted_comments = value;
524 self
525 }
526 #[must_use]
528 pub const fn with_normalize_newlines(mut self, value: bool) -> Self {
529 self.normalize_newlines = value;
530 self
531 }
532 #[must_use]
534 pub const fn with_malformed_lines(mut self, value: MalformedLines) -> Self {
535 self.malformed_lines = value;
536 self
537 }
538 #[must_use]
540 pub const fn with_node_object_keys(mut self, value: bool) -> Self {
541 self.node_object_keys = value;
542 self
543 }
544 #[must_use]
546 pub const fn with_line_byte_limit(mut self, value: Option<usize>) -> Self {
547 self.line_byte_limit = value;
548 self
549 }
550}
551impl Default for Dialect {
552 fn default() -> Self {
553 Self::PORTABLE
554 }
555}