rucc_tuple/error.rs
1//! What goes wrong when a tuple is read, and what the user is told about it.
2
3use core::fmt;
4
5use crate::{Abi, Arch, Endian, Env, Os, SubArch};
6
7/// A tuple that could not be read, or that was read and does not describe a machine.
8///
9/// Every variant names the component it is unhappy about. That is the whole design goal of this
10/// type: the model this replaces had a catch-all arm that skipped anything it did not recognize,
11/// so `x86_64-linux-gnu.2.28` parsed as `x86_64-linux-gnu` and the version was thrown away with
12/// no diagnostic. A user who pins a glibc version and gets the host's is not going to find out
13/// until the binary fails on the target machine.
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum Error {
16 /// The tuple was empty or all separators.
17 Empty,
18 /// The leading component is not an architecture we know.
19 UnknownArch(String),
20 /// The OS component is not an OS we know.
21 UnknownOs(String),
22 /// The environment component is not an environment we know.
23 UnknownEnv(String),
24 /// Components were left over after the environment was read.
25 ///
26 /// This is the case the old catch-all silently ate, so it is an error with the leftovers
27 /// quoted rather than a shrug.
28 Trailing(Vec<String>),
29 /// A version was attached to a component and could not be read as one.
30 BadVersion {
31 /// The component the version was attached to, for the message.
32 component: &'static str,
33 /// What was found where a version was expected.
34 found: String,
35 },
36 /// A sub-architecture was named that does not belong to the architecture.
37 SubArchMismatch {
38 /// The architecture that was named.
39 arch: Arch,
40 /// The baseline that does not belong to it.
41 sub_arch: SubArch,
42 },
43 /// A byte order was named that the architecture does not have.
44 EndianUnsupported {
45 /// The architecture that was named.
46 arch: Arch,
47 /// The byte order it does not have.
48 endian: Endian,
49 },
50 /// An environment was named that the OS does not have.
51 EnvMismatch {
52 /// The OS that was named.
53 os: Os,
54 /// The environment it does not have.
55 env: Env,
56 },
57 /// A float ABI was named for an architecture that has one calling convention.
58 AbiMismatch {
59 /// The architecture that was named.
60 arch: Arch,
61 /// The ABI it cannot select.
62 abi: Abi,
63 },
64 /// A version was attached to a component that does not take one.
65 ///
66 /// `x86_64-linux.5.15-gnu` is not a request for a kernel version, it is a mistake, and
67 /// accepting it would mean the tuple carries a field nothing reads.
68 VersionNotAccepted {
69 /// The component the version was attached to.
70 component: &'static str,
71 },
72}
73
74impl fmt::Display for Error {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 match self {
77 Error::Empty => write!(f, "empty target tuple"),
78 Error::UnknownArch(found) => {
79 write!(f, "unknown architecture `{found}`")
80 }
81 Error::UnknownOs(found) => write!(f, "unknown operating system `{found}`"),
82 Error::UnknownEnv(found) => write!(f, "unknown environment `{found}`"),
83 Error::Trailing(rest) => {
84 write!(f, "unexpected trailing component")?;
85 if rest.len() > 1 {
86 f.write_str("s")?;
87 }
88 for (i, part) in rest.iter().enumerate() {
89 if i == 0 {
90 write!(f, " `{part}`")?;
91 } else {
92 write!(f, ", `{part}`")?;
93 }
94 }
95 Ok(())
96 }
97 Error::BadVersion { component, found } => {
98 write!(f, "`{found}` is not a version for the {component} component")
99 }
100 Error::SubArchMismatch { arch, sub_arch } => {
101 write!(f, "`{}` is not a baseline of `{arch}`", sub_arch.as_str())
102 }
103 Error::EndianUnsupported { arch, endian } => {
104 write!(f, "`{arch}` has no {endian} endian mode")
105 }
106 Error::EnvMismatch { os, env } => {
107 write!(f, "`{os}` has no `{env}` environment")
108 }
109 Error::AbiMismatch { arch, abi } => {
110 write!(f, "`{arch}` has one calling convention and cannot select `{abi}`")
111 }
112 Error::VersionNotAccepted { component } => {
113 write!(f, "the {component} component does not take a version")
114 }
115 }
116 }
117}
118
119impl std::error::Error for Error {}