port print utils + refactoring
[hiphop-php.git] / hphp / hack / src / hhbc / write.rs
blob311978f207cce34efb4c43fd47a0413f805ea683
1 // Copyright (c) Facebook, Inc. and its affiliates.
2 //
3 // This source code is licensed under the MIT license found in the
4 // LICENSE file in the "hack" directory of this source tree.
5 #![allow(unused_variables)]
6 #![allow(dead_code)]
8 use std::{
9     fmt::{self, Debug},
10     io,
12 use thiserror::Error;
14 pub type Result<T, WE> = std::result::Result<T, Error<WE>>;
16 #[macro_export]
17 macro_rules! not_impl {
18     () => {
19         Err(Error::NotImpl(format!("{}:{}", file!(), line!())))
20     };
23 #[derive(Error, Debug)]
24 pub enum Error<WE: Debug> {
25     #[error("write error: {0:?}")]
26     WriteError(WE),
28     #[error("a string may contain invalid utf-8")]
29     InvalidUTF8,
31     //TODO(hrust): This is a temp error during porting
32     #[error("NOT_IMPL: {0}")]
33     NotImpl(String),
35     #[error("Failed: {0}")]
36     Fail(String),
39 impl<WE: Debug> Error<WE> {
40     pub fn fail(s: impl Into<String>) -> Self {
41         Self::Fail(s.into())
42     }
45 pub trait Write {
46     type Error: Debug;
47     fn write(&mut self, s: impl AsRef<str>) -> Result<(), Self::Error>;
49     fn write_if(&mut self, cond: bool, s: impl AsRef<str>) -> Result<(), Self::Error> {
50         if cond {
51             self.write(s)
52         } else {
53             Ok(())
54         }
55     }
58 impl<W: fmt::Write> Write for W {
59     type Error = fmt::Error;
60     fn write(&mut self, s: impl AsRef<str>) -> Result<(), Self::Error> {
61         self.write_str(s.as_ref()).map_err(Error::WriteError)
62     }
65 pub struct IoWrite(Box<dyn io::Write + Send>);
67 impl IoWrite {
68     pub fn new(w: impl io::Write + 'static + Send) -> Self {
69         Self(Box::new(w))
70     }
72     pub fn flush(&mut self) -> std::result::Result<(), io::Error> {
73         self.0.flush()
74     }
77 impl Write for IoWrite {
78     type Error = std::io::Error;
79     fn write(&mut self, s: impl AsRef<str>) -> Result<(), Self::Error> {
80         self.0
81             .write_all(s.as_ref().as_bytes())
82             .map_err(Error::WriteError)
83     }
86 pub fn newline<W: Write>(w: &mut W) -> Result<(), W::Error> {
87     w.write("\n")
90 pub fn wrap_by_<W, F>(w: &mut W, s: &str, e: &str, f: F) -> Result<(), W::Error>
91 where
92     W: Write,
93     F: FnOnce(&mut W) -> Result<(), W::Error>,
95     w.write(s)?;
96     f(w)?;
97     w.write(e)
100 pub fn wrap_by<W: Write, F>(w: &mut W, s: &str, f: F) -> Result<(), W::Error>
101 where
102     F: FnOnce(&mut W) -> Result<(), W::Error>,
104     wrap_by_(w, s, s, f)
107 pub fn wrap_by_braces<W: Write, F>(w: &mut W, f: F) -> Result<(), W::Error>
108 where
109     F: FnOnce(&mut W) -> Result<(), W::Error>,
111     wrap_by_(w, "{", "}", f)
114 pub fn wrap_by_paren<W: Write, F>(w: &mut W, f: F) -> Result<(), W::Error>
115 where
116     F: FnOnce(&mut W) -> Result<(), W::Error>,
118     wrap_by_(w, "(", ")", f)
121 pub fn wrap_by_quotes<W: Write, F>(w: &mut W, f: F) -> Result<(), W::Error>
122 where
123     F: FnOnce(&mut W) -> Result<(), W::Error>,
125     wrap_by_(w, "\"", "\"", f)
128 pub fn wrap_by_triple_quotes<W: Write, F>(w: &mut W, f: F) -> Result<(), W::Error>
129 where
130     F: FnOnce(&mut W) -> Result<(), W::Error>,
132     wrap_by_(w, "\"\"\"", "\"\"\"", f)
135 pub fn wrap_by_angle<W: Write, F>(w: &mut W, f: F) -> Result<(), W::Error>
136 where
137     F: FnOnce(&mut W) -> Result<(), W::Error>,
139     wrap_by_(w, "<", ">", f)
142 pub fn wrap_by_square<W: Write, F>(w: &mut W, f: F) -> Result<(), W::Error>
143 where
144     F: FnOnce(&mut W) -> Result<(), W::Error>,
146     wrap_by_(w, "[", "]", f)
149 pub fn write_list<W: Write>(w: &mut W, items: &[impl AsRef<str>]) -> Result<(), W::Error> {
150     Ok(for i in items {
151         w.write(i.as_ref())?;
152     })
155 pub fn concat_str<W: Write, I: AsRef<str>>(w: &mut W, ss: impl AsRef<[I]>) -> Result<(), W::Error> {
156     concat(w, ss, |w, s| w.write(s))
159 pub fn concat_str_by<W: Write, I: AsRef<str>>(
160     w: &mut W,
161     sep: impl AsRef<str>,
162     ss: impl AsRef<[I]>,
163 ) -> Result<(), W::Error> {
164     concat_by(w, sep, ss, |w, s| w.write(s))
167 pub fn concat<W, T, F>(w: &mut W, items: impl AsRef<[T]>, f: F) -> Result<(), W::Error>
168 where
169     W: Write,
170     F: FnMut(&mut W, &T) -> Result<(), W::Error>,
172     concat_by(w, "", items, f)
175 pub fn concat_by<W, T, F>(
176     w: &mut W,
177     sep: impl AsRef<str>,
178     items: impl AsRef<[T]>,
179     mut f: F,
180 ) -> Result<(), W::Error>
181 where
182     W: Write,
183     F: FnMut(&mut W, &T) -> Result<(), W::Error>,
185     let mut first = true;
186     let sep = sep.as_ref();
187     Ok(for i in items.as_ref() {
188         if first {
189             first = false;
190         } else {
191             w.write(sep)?;
192         }
193         f(w, i)?;
194     })
197 pub fn option<W: Write, T, F>(w: &mut W, i: impl Into<Option<T>>, f: F) -> Result<(), W::Error>
198 where
199     F: Fn(&mut W, T) -> Result<(), W::Error>,
201     match i.into() {
202         None => Ok(()),
203         Some(i) => f(w, i),
204     }
207 pub fn option_or<W: Write, T, F>(
208     w: &mut W,
209     i: impl Into<Option<T>>,
210     f: F,
211     default: impl AsRef<str>,
212 ) -> Result<(), W::Error>
213 where
214     F: Fn(&mut W, T) -> Result<(), W::Error>,
216     match i.into() {
217         None => w.write(default),
218         Some(i) => f(w, i),
219     }