trait_bound_pretty/
lib.rs1use std::io::Write;
2
3use lalrpop_util::lalrpop_mod;
4
5lalrpop_mod!(pub parser);
6#[cfg(test)]
7mod parser_tests;
8
9pub trait Pretty {
10 fn pretty_to<Writer: Write>(&self, writer: &mut Writer) -> Result<(), std::io::Error>;
14
15 fn pretty(&self) -> String {
17 let mut writer = Vec::new();
18 self.pretty_to(&mut writer)
19 .expect("writing to Vec<u8> should never fail");
20 String::from_utf8(writer).expect("we only ever write valid utf8")
21 }
22}
23
24#[derive(Debug)]
25pub enum Bound<'a> {
26 Lifetime(&'a str),
27 Item(Item<'a>),
28 Reference {
29 lifetime: &'a str,
30 mut_: bool,
31 item: Item<'a>,
32 },
33 Tuple(Vec<Bound<'a>>),
34}
35
36impl<'a> Bound<'a> {
37 fn pretty_internal<Writer: Write>(
38 &self,
39 indent_level: usize,
40 writer: &mut Writer,
41 ) -> Result<(), std::io::Error> {
42 indent(indent_level, writer)?;
43 match self {
44 Self::Lifetime(lifetime) => writer.write_all(lifetime.as_bytes()),
45 Self::Item(item) => item.pretty_internal(indent_level, writer),
46 Self::Reference {
47 lifetime,
48 mut_,
49 item,
50 } => {
51 writer.write_all(b"&")?;
52 writer.write_all(lifetime.as_bytes())?;
53 if *mut_ {
54 writer.write_all(b" mut")?;
55 }
56 writer.write_all(b" ")?;
57 item.pretty_internal(indent_level, writer)
58 }
59 Self::Tuple(bounds) => {
60 writer.write_all(b"(\n")?;
61 for (idx, bound) in bounds.iter().enumerate() {
62 bound.pretty_internal(indent_level + 1, writer)?;
63 if idx != bounds.len() - 1 {
64 writer.write_all(b",")?;
65 }
66 writer.write_all(b"\n")?;
67 }
68 indent(indent_level, writer)?;
69 writer.write_all(b")")
70 }
71 }
72 }
73}
74
75#[derive(Debug)]
77pub struct Item<'a> {
78 name: Vec<&'a str>,
80 generic_bounds: Vec<Bound<'a>>,
81}
82
83impl<'a> Item<'a> {
84 fn pretty_internal<Writer: Write>(
85 &self,
86 indent_level: usize,
87 writer: &mut Writer,
88 ) -> Result<(), std::io::Error> {
89 for (idx, component) in self.name.iter().enumerate().rev() {
90 writer.write_all(component.as_bytes())?;
91 if idx != 0 {
92 writer.write_all(b"::")?;
93 }
94 }
95 if !self.generic_bounds.is_empty() {
96 writer.write_all(b"<\n")?;
97 for (idx, bound) in self.generic_bounds.iter().enumerate() {
98 bound.pretty_internal(indent_level + 1, writer)?;
99 if idx != self.generic_bounds.len() - 1 {
100 writer.write_all(b",")?;
101 }
102 writer.write_all(b"\n")?;
103 }
104 indent(indent_level, writer)?;
105 writer.write_all(b">")?;
106 }
107 Ok(())
108 }
109}
110
111impl<'a> Pretty for Item<'a> {
112 fn pretty_to<Writer: Write>(&self, writer: &mut Writer) -> Result<(), std::io::Error> {
113 self.pretty_internal(0, writer)
114 }
115}
116
117const INDENT: &'static [u8] = b" ";
118fn indent<Writer: Write>(indent_level: usize, writer: &mut Writer) -> Result<(), std::io::Error> {
119 for _ in 0..indent_level {
120 writer.write_all(INDENT)?;
121 }
122 Ok(())
123}
124
125#[derive(Debug)]
126pub struct E0277<'a> {
127 item: Item<'a>,
128 trait_bound: Item<'a>,
129}
130
131impl<'a> Pretty for E0277<'a> {
132 fn pretty_to<Writer: Write>(&self, writer: &mut Writer) -> Result<(), std::io::Error> {
134 writer.write_all(b"error[E0277]: the item:\n")?;
135 writer.write_all(INDENT)?;
136 self.item.pretty_internal(1, writer)?;
137 writer.write_all(b"\ndoes not satisfy the trait bound:\n")?;
138 writer.write_all(INDENT)?;
139 self.trait_bound.pretty_internal(1, writer)?;
140 Ok(())
141 }
142}