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
#![cfg_attr(rustfmt, rustfmt::skip)]
use super::*;
/// Helper for the generation of C headers.
///
/// Defining C headers requires _two_ abstractions:
///
/// - set-like lookup by name, to ensure each type is defined at most once;
///
/// - a [`Write`][`::std::io::Write`]able "out stream", where the headers
/// should be written to.
///
/// This trait minimally combines both abstractions, and in exchange offers an
/// auto-implemented non-overridable
/// [`Definer::define_once`]`()`.
pub
trait Definer : define_once_seal::__ {
/// Must return `true` iff an actual `insert` happened.
fn insert (self: &'_ mut Self, name: &'_ str)
-> bool
;
/// Yields a handle to the underlying [`Write`][`io::Write`]r
fn out (self: &'_ mut Self)
-> &'_ mut dyn io::Write
;
#[cfg(docs)]
/// Convenience method to perform an [`.insert()`][`Definer::insert`] so
/// that if it succeeds (thus guaranteeing the call happens for the first
/// time), it calls `write_typedef` on itself.
///
/// **This method cannot be overriden**.
fn define_once (
self: &'_ mut Self,
name: &'_ str,
write_typedef: &'_ mut dyn
FnMut (&'_ mut dyn Definer) -> io::Result<()>
,
) -> io::Result<()>
{ unreachable!("See `define_once_seal::__::define_once` for the impl") }
}
mod define_once_seal {
use super::*;
pub
trait __ {
fn define_once (
self: &'_ mut Self,
name: &'_ str,
write_typedef: &'_ mut dyn
FnMut(&'_ mut dyn Definer) -> io::Result<()>
,
) -> io::Result<()>
;
}
impl<T : Definer> __
for T
{
fn define_once (
self: &'_ mut Self,
name: &'_ str,
write_typedef: &'_ mut dyn
FnMut(&'_ mut dyn Definer) -> io::Result<()>
,
) -> io::Result<()>
{
if self.insert(name) {
write_typedef(self)?;
}
Ok(())
}
}
}
/// Simplest implementation of a [`Definer`]:
/// a `HashSet<String>, &'_ mut dyn Write` pair.
pub
struct HashSetDefiner<'out> {
pub
defines_set: HashSet<String>,
pub
out: &'out mut dyn io::Write,
}
impl Definer
for HashSetDefiner<'_>
{
fn insert (self: &'_ mut Self, name: &'_ str)
-> bool
{
self.defines_set
.insert(name.to_owned())
}
fn out (self: &'_ mut Self)
-> &'_ mut dyn io::Write
{
&mut *self.out
}
}