rust_toolchain_file/
lib.rs1pub use {legacy::LegacyToolchainFile, toml::RustToolchainToml};
5
6pub mod legacy;
7pub mod toml;
8
9#[cfg(test)]
10mod tests;
11
12#[derive(Debug, PartialEq)]
14pub enum ToolchainFile {
15 Legacy(LegacyToolchainFile),
17 Toml(RustToolchainToml),
19}
20
21#[derive(Debug, Copy, Clone, PartialEq)]
23pub enum Variant {
24 Legacy,
25 Toml,
26}
27
28impl Variant {
29 fn parse_with(&self, content: &str) -> Result<ToolchainFile, ParserError> {
30 match *self {
31 Self::Legacy => legacy::Parser::new(content)
32 .parse()
33 .map(ToolchainFile::Legacy)
34 .map_err(From::from),
35 Self::Toml => toml::Parser::new(content)
36 .parse()
37 .map(ToolchainFile::Toml)
38 .map_err(From::from),
39 }
40 }
41}
42
43#[derive(Debug, Copy, Clone, PartialEq)]
46pub enum ParseStrategy {
47 Only(Variant),
48 Fallback {
49 first: Variant,
50 fallback_to: Variant,
51 },
52}
53
54pub struct Parser<'content> {
56 content: &'content str,
57
58 parse_option: ParseStrategy,
59}
60
61impl<'content> Parser<'content> {
62 pub fn new(content: &'content str, parse_option: ParseStrategy) -> Self {
63 Self {
64 content,
65 parse_option,
66 }
67 }
68}
69
70impl Parser<'_> {
71 pub fn parse(&self) -> Result<ToolchainFile, ParserError> {
72 match self.parse_option {
73 ParseStrategy::Only(v) => v.parse_with(self.content),
74 ParseStrategy::Fallback { first, fallback_to } => {
75 first.parse_with(self.content).or_else(|original_err| {
76 fallback_to
77 .parse_with(self.content)
78 .map_err(|fallback_err| {
79 ParserError::FallbackError(FallbackError {
80 first: Box::new(original_err),
81 fallback_to: Box::new(fallback_err),
82 })
83 })
84 })
85 }
86 }
87 }
88}
89
90#[derive(Debug, thiserror::Error, PartialEq)]
91pub enum ParserError {
92 #[error("Failed to parse legacy toolchain-file variant: {0}")]
93 LegacyParseError(#[from] legacy::ParserError),
94
95 #[error("Failed to parse TOML toolchain-file variant: {0}")]
96 TomlParseError(#[from] toml::ParserError),
97
98 #[error("Both original and fallback parse attempts failed: {0}")]
99 FallbackError(FallbackError),
100}
101
102#[derive(Debug, PartialEq, thiserror::Error)]
103#[error("Failed to parse: '{first}' and failed to fallback on '{fallback_to}'")]
104pub struct FallbackError {
105 first: Box<ParserError>,
106 fallback_to: Box<ParserError>,
107}
108
109impl FallbackError {
110 pub fn first(&self) -> &ParserError {
111 self.first.as_ref()
112 }
113
114 pub fn fallback_to(&self) -> &ParserError {
115 self.fallback_to.as_ref()
116 }
117}