/rust/registry/src/index.crates.io-1949cf8c6b5b557f/writeable-0.6.3/src/concat.rs
Line | Count | Source |
1 | | // This file is part of ICU4X. For terms of use, please see the file |
2 | | // called LICENSE at the top level of the ICU4X source tree |
3 | | // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). |
4 | | |
5 | | use crate::TryWriteable; |
6 | | use crate::Writeable; |
7 | | use core::fmt; |
8 | | |
9 | | /// A [`Writeable`] that efficiently concatenates two other [`Writeable`]s. |
10 | | /// |
11 | | /// See the [`concat_writeable!`] macro for a convenient way to make one of these. |
12 | | /// |
13 | | /// # Examples |
14 | | /// |
15 | | /// ``` |
16 | | /// use writeable::adapters::Concat; |
17 | | /// use writeable::assert_writeable_eq; |
18 | | /// |
19 | | /// assert_writeable_eq!(Concat("Number: ", 25), "Number: 25"); |
20 | | /// ``` |
21 | | /// |
22 | | /// With [`TryWriteable`]: |
23 | | /// |
24 | | /// ``` |
25 | | /// use writeable::adapters::Concat; |
26 | | /// use writeable::assert_try_writeable_eq; |
27 | | /// use writeable::TryWriteable; |
28 | | /// |
29 | | /// struct AlwaysPanic; |
30 | | /// |
31 | | /// impl TryWriteable for AlwaysPanic { |
32 | | /// type Error = &'static str; |
33 | | /// fn try_write_to_parts<W: writeable::PartsWrite + ?Sized>( |
34 | | /// &self, |
35 | | /// _sink: &mut W, |
36 | | /// ) -> Result<Result<(), Self::Error>, core::fmt::Error> { |
37 | | /// // Unreachable panic: the first Writeable errors, |
38 | | /// // so the second Writeable is not evaluated. |
39 | | /// panic!("this is a test to demonstrate unreachable code") |
40 | | /// } |
41 | | /// } |
42 | | /// |
43 | | /// let writeable0: Result<&str, &str> = Err("error message"); |
44 | | /// let writeable1 = AlwaysPanic; |
45 | | /// |
46 | | /// assert_try_writeable_eq!( |
47 | | /// Concat(writeable0, writeable1), |
48 | | /// "error message", |
49 | | /// Err("error message"), |
50 | | /// ) |
51 | | /// ``` |
52 | | #[derive(Debug)] |
53 | | #[allow(clippy::exhaustive_structs)] // designed for nesting |
54 | | pub struct Concat<A, B>(pub A, pub B); |
55 | | |
56 | | impl<A, B> Writeable for Concat<A, B> |
57 | | where |
58 | | A: Writeable, |
59 | | B: Writeable, |
60 | | { |
61 | | #[inline] |
62 | 0 | fn write_to<W: fmt::Write + ?Sized>(&self, sink: &mut W) -> fmt::Result { |
63 | 0 | self.0.write_to(sink)?; |
64 | 0 | self.1.write_to(sink) |
65 | 0 | } |
66 | | #[inline] |
67 | 0 | fn write_to_parts<S: crate::PartsWrite + ?Sized>(&self, sink: &mut S) -> fmt::Result { |
68 | 0 | self.0.write_to_parts(sink)?; |
69 | 0 | self.1.write_to_parts(sink) |
70 | 0 | } |
71 | | #[inline] |
72 | 0 | fn writeable_length_hint(&self) -> crate::LengthHint { |
73 | 0 | self.0.writeable_length_hint() + self.1.writeable_length_hint() |
74 | 0 | } |
75 | | } |
76 | | |
77 | | impl<A, B, E> TryWriteable for Concat<A, B> |
78 | | where |
79 | | A: TryWriteable<Error = E>, |
80 | | B: TryWriteable<Error = E>, |
81 | | { |
82 | | type Error = E; |
83 | | #[inline] |
84 | 0 | fn try_write_to<W: fmt::Write + ?Sized>( |
85 | 0 | &self, |
86 | 0 | sink: &mut W, |
87 | 0 | ) -> Result<Result<(), Self::Error>, fmt::Error> { |
88 | 0 | if let Err(e) = self.0.try_write_to(sink)? { |
89 | 0 | return Ok(Err(e)); |
90 | 0 | } |
91 | 0 | self.1.try_write_to(sink) |
92 | 0 | } |
93 | | #[inline] |
94 | 0 | fn try_write_to_parts<S: crate::PartsWrite + ?Sized>( |
95 | 0 | &self, |
96 | 0 | sink: &mut S, |
97 | 0 | ) -> Result<Result<(), Self::Error>, fmt::Error> { |
98 | 0 | if let Err(e) = self.0.try_write_to_parts(sink)? { |
99 | 0 | return Ok(Err(e)); |
100 | 0 | } |
101 | 0 | self.1.try_write_to_parts(sink) |
102 | 0 | } |
103 | | #[inline] |
104 | 0 | fn writeable_length_hint(&self) -> crate::LengthHint { |
105 | 0 | self.0.writeable_length_hint() + self.1.writeable_length_hint() |
106 | 0 | } |
107 | | } |
108 | | |
109 | | impl<A, B> fmt::Display for Concat<A, B> |
110 | | where |
111 | | A: Writeable, |
112 | | B: Writeable, |
113 | | { |
114 | | #[inline] |
115 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
116 | 0 | self.0.write_to(f)?; |
117 | 0 | self.1.write_to(f) |
118 | 0 | } |
119 | | } |
120 | | |
121 | | /// Returns a [`Writeable`] concatenating any number of [`Writeable`]s. |
122 | | /// |
123 | | /// The macro resolves to a nested [`Concat`]. |
124 | | /// |
125 | | /// # Examples |
126 | | /// |
127 | | /// ``` |
128 | | /// use writeable::assert_writeable_eq; |
129 | | /// |
130 | | /// let concatenated = writeable::concat_writeable!("Health: ", 5, '/', 8); |
131 | | /// |
132 | | /// assert_writeable_eq!(concatenated, "Health: 5/8"); |
133 | | /// ``` |
134 | | #[macro_export] |
135 | | #[doc(hidden)] // macro |
136 | | macro_rules! __concat_writeable { |
137 | | // Base case: |
138 | | ($x:expr) => ($x); |
139 | | // `$x` followed by at least one `$y,` |
140 | | ($x:expr, $($y:expr),+) => ( |
141 | | // Call `concat_writeable!` recursively on the tail `$y` |
142 | | $crate::adapters::Concat($x, $crate::concat_writeable!($($y),+)) |
143 | | ) |
144 | | } |
145 | | #[doc(inline)] |
146 | | pub use __concat_writeable as concat_writeable; |