{% if td.clz_description %}/// {{ td.clz_description }}{% endif %}
{% if td.clz_is_trait %}{% if td.set_trait_typetag %}#[typetag::serde(tag = "@struct")]{% endif %}{% else %}#[derive(Debug, {% if not td.has_trait_field %}Clone, {% endif %}Serialize, Deserialize, TypedBuilder)]{% endif %}
{% if not td.is_private %}pub {% endif %}{% if td.clz_is_trait %}trait{% else %}struct{% endif %} {{ td.clz_name }}{% if td.clz_is_trait %}: {% if td.clz_name != 'Object' %}Object + {% endif %}RObject + Debug {}{% else %} {
  #[doc(hidden)]
  #[serde(rename(serialize = "@type", deserialize = "@type"))]
  #[builder(default="{{ td.origin_name }}".to_string())]
  td_name: String, // {{ td.origin_name }}
  {% if td.fields %}{% for field in td.fields %}/// {{field.description}}
  {% if field.name == 'type_' %}#[serde(rename(serialize = "type", deserialize = "type"))] {% endif %}#[builder(default)] {{field.name}}: {{field.class | field_type(td = td, field_name = field.name, wrap_option = true)}},
  {% endfor %}{% endif %}
}
{% endif %}
{% if td.has_trait_field %}
impl Clone for {{ td.clz_name }} {
  fn clone(&self) -> Self { rtd_clone!()(self) }
}
{% endif %}
{% if not td.clz_is_trait %}
impl Object for {{ td.clz_name }} {}
impl RObject for {{ td.clz_name }} {
  #[doc(hidden)] fn td_name(&self) -> &'static str { "{{ td.origin_name }}" }
  fn td_type(&self) -> RTDType { RTDType::{{ td.clz_name }} }
  fn to_json(&self) -> String { rtd_to_json!()(self) }
}
{% endif %}
{% if td.clz_super and td.clz_super != 'Object' and td.clz_super != 'TlObject' %}
{% if td.impl_trait_typetag %}#[typetag::serde] {% endif %}impl {{ td.clz_super }} for {{ td.clz_name }} {}
{% endif %}
{% if not td.is_private and not td.clz_is_trait %}
impl {{ td.clz_name }} {
  {% if td.fields %}{% for field in td.fields %}
  pub fn {{field.name}}(&self) -> {{field.class | field_type(td = td, field_name = field.name, wrap_option = true)}} { self.{{field.name}}.clone() }
  {% endfor %}{% endif %}
  pub fn from_json<S: AsRef<str>>(json: S) -> Option<Self> { from_json!()(json.as_ref()) }
}
{% endif %}
{% if td.clz_is_trait %}
{% if td.clz_name != 'Object' and td.clz_name != 'Function' %}
impl {{ td.clz_name }} {
  pub fn from_json<S: AsRef<str>>(json: S) -> Option<Box<Self>> { from_json!()(json.as_ref()) }
}
impl Clone for Box<{{td.clz_name}}> {
  fn clone(&self) -> Self { rtd_clone!()(self) }
}
{% endif %}
{% if td.has_subclasses and td.clz_name != 'Object' %}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, EnumString)]
pub enum RTD{{td.clz_name}}Type {
  {% for sub in td.sub_classes %}{{ sub.name }},
  {% endfor %}
}
impl RTD{{td.clz_name}}Type {
  pub fn of<S: AsRef<str>>(text: S) -> Option<Self> { rtd_of!(RTD{{td.clz_name}}Type)(text.as_ref()) }
}
{% endif %}
{% endif %}
