in src/bindgen/language_backend/clike.rs [119:338]
fn write_derived_cpp_ops<W: Write>(&mut self, out: &mut SourceWriter<W>, s: &Struct) {
let mut wrote_start_newline = false;
if self.config.structure.derive_constructor(&s.annotations) && !s.fields.is_empty() {
if !wrote_start_newline {
wrote_start_newline = true;
out.new_line();
}
out.new_line();
let renamed_fields: Vec<_> = s
.fields
.iter()
.map(|field| {
self.config
.function
.rename_args
.apply(&field.name, IdentifierType::FunctionArg)
.into_owned()
})
.collect();
write!(out, "{}(", s.export_name());
let vec: Vec<_> = s
.fields
.iter()
.zip(&renamed_fields)
.map(|(field, renamed)| {
Field::from_name_and_type(
// const-ref args to constructor
format!("const& {}", renamed),
field.ty.clone(),
)
})
.collect();
out.write_vertical_source_list(self, &vec[..], ListType::Join(","), Self::write_field);
write!(out, ")");
out.new_line();
write!(out, " : ");
let vec: Vec<_> = s
.fields
.iter()
.zip(&renamed_fields)
.map(|(field, renamed)| format!("{}({})", field.name, renamed))
.collect();
out.write_vertical_source_list(self, &vec[..], ListType::Join(","), |_, out, s| {
write!(out, "{}", s)
});
out.new_line();
write!(out, "{{}}");
out.new_line();
}
let other = self
.config
.function
.rename_args
.apply("other", IdentifierType::FunctionArg);
if s.annotations
.bool("internal-derive-bitflags")
.unwrap_or(false)
{
assert_eq!(s.fields.len(), 1);
let bits = &s.fields[0].name;
if !wrote_start_newline {
wrote_start_newline = true;
out.new_line();
}
let constexpr_prefix = if self.config.constant.allow_constexpr {
"constexpr "
} else {
""
};
out.new_line();
write!(out, "{}explicit operator bool() const", constexpr_prefix);
out.open_brace();
write!(out, "return !!{bits};");
out.close_brace(false);
out.new_line();
write!(
out,
"{}{} operator~() const",
constexpr_prefix,
s.export_name()
);
out.open_brace();
write!(
out,
"return {} {{ static_cast<decltype({bits})>(~{bits}) }};",
s.export_name()
);
out.close_brace(false);
s.emit_bitflags_binop(constexpr_prefix, '|', &other, out);
s.emit_bitflags_binop(constexpr_prefix, '&', &other, out);
s.emit_bitflags_binop(constexpr_prefix, '^', &other, out);
}
// Generate a serializer function that allows dumping this struct
// to an std::ostream. It's defined as a friend function inside the
// struct definition, and doesn't need the `inline` keyword even
// though it's implemented right in the generated header file.
if self.config.structure.derive_ostream(&s.annotations) {
if !wrote_start_newline {
wrote_start_newline = true;
out.new_line();
}
out.new_line();
let stream = self
.config
.function
.rename_args
.apply("stream", IdentifierType::FunctionArg);
let instance = self
.config
.function
.rename_args
.apply("instance", IdentifierType::FunctionArg);
write!(
out,
"friend std::ostream& operator<<(std::ostream& {}, const {}& {})",
stream,
s.export_name(),
instance,
);
out.open_brace();
write!(out, "return {} << \"{{ \"", stream);
let vec: Vec<_> = s
.fields
.iter()
.map(|x| format!(" << \"{}=\" << {}.{}", x.name, instance, x.name))
.collect();
out.write_vertical_source_list(
self,
&vec[..],
ListType::Join(" << \", \""),
|_, out, s| write!(out, "{}", s),
);
out.write(" << \" }\";");
out.close_brace(false);
}
let skip_fields = s.has_tag_field as usize;
macro_rules! emit_op {
($op_name:expr, $op:expr, $conjuc:expr) => {{
if !wrote_start_newline {
#[allow(unused_assignments)]
{
wrote_start_newline = true;
}
out.new_line();
}
out.new_line();
if let Some(Some(attrs)) = s.annotations.atom(concat!($op_name, "-attributes")) {
write!(out, "{} ", attrs);
}
write!(
out,
"bool operator{}(const {}& {}) const",
$op,
s.export_name(),
other
);
out.open_brace();
out.write("return ");
let vec: Vec<_> = s
.fields
.iter()
.skip(skip_fields)
.map(|field| format!("{} {} {}.{}", field.name, $op, other, field.name))
.collect();
out.write_vertical_source_list(
self,
&vec[..],
ListType::Join(&format!(" {}", $conjuc)),
|_, out, s| write!(out, "{}", s),
);
out.write(";");
out.close_brace(false);
}};
}
if self.config.structure.derive_eq(&s.annotations) && s.can_derive_eq() {
emit_op!("eq", "==", "&&");
}
if self.config.structure.derive_neq(&s.annotations) && s.can_derive_eq() {
emit_op!("neq", "!=", "||");
}
if self.config.structure.derive_lt(&s.annotations)
&& s.fields.len() == 1
&& s.fields[0].ty.can_cmp_order()
{
emit_op!("lt", "<", "&&");
}
if self.config.structure.derive_lte(&s.annotations)
&& s.fields.len() == 1
&& s.fields[0].ty.can_cmp_order()
{
emit_op!("lte", "<=", "&&");
}
if self.config.structure.derive_gt(&s.annotations)
&& s.fields.len() == 1
&& s.fields[0].ty.can_cmp_order()
{
emit_op!("gt", ">", "&&");
}
if self.config.structure.derive_gte(&s.annotations)
&& s.fields.len() == 1
&& s.fields[0].ty.can_cmp_order()
{
emit_op!("gte", ">=", "&&");
}
}