1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//! Error and warning types shared by every conversion direction.
/// Reason a conversion can fail.
///
/// The `NotImplemented` variant is the placeholder every
/// pre-implementation function returns. Subsequent issues
/// (#2053 iReal→ChordPro, #2061 ChordPro→iReal) replace those
/// returns with real implementations; new variants are added at
/// the bottom of the enum to preserve compatibility with code that
/// matches on the existing variants.
///
/// Marked `#[non_exhaustive]` so adding a new variant in a follow-up
/// PR is non-breaking for downstream `match` expressions, matching
/// the additive-evolution contract documented at the crate root.
///
/// # Note for future implementers
///
/// Once #2053 / #2061 land, [`Self::InvalidSource`] and
/// [`Self::UnrepresentableTarget`] will carry parser-derived,
/// potentially attacker-controlled text. Implementations SHOULD
/// truncate or sanitise their messages before constructing these
/// variants; downstream `Display` consumers and log forwarders
/// MUST NOT assume bounded length until that bound is enforced
/// upstream. (Same pattern as `chordsketch_ireal::json::truncate_for_message`.)
/// A non-fatal information loss recorded during conversion.
///
/// Conversions return `Ok(ConversionOutput { warnings, .. })` for
/// lossy-but-successful runs; callers decide whether to fail on a
/// non-empty warning list. This keeps the strictness policy in the
/// caller's hands rather than baking it into the converter.
///
/// Marked `#[non_exhaustive]` so additional diagnostic fields can be
/// appended in a follow-up PR without breaking downstream code that
/// currently constructs `ConversionWarning` values only via
/// [`ConversionWarning::new`].
/// Class of information loss in a [`ConversionWarning`].
///
/// New variants are appended; existing variants are stable across
/// minor versions. Marked `#[non_exhaustive]` so adding a variant
/// is non-breaking for downstream `match` arms.
///
/// `Copy` is intentional here because every variant is fieldless,
/// matching the per-warning struct (`ConversionWarning`) which
/// owns the attached message and is therefore not `Copy`.