{% if clz_description %}/// {{ clz_description }}{% endif %}
{% if clz_is_trait %}{% if set_trait_typetag %}#[typetag::serde(tag = "@struct")]{% endif %}{% else %}#[derive(Debug, {% if not has_trait_field %}Clone, {% endif %}Serialize, Deserialize)]{% endif %}
{% if not is_private %}pub {% endif %}{% if clz_is_trait %}trait{% else %}struct{% endif %} {{ clz_name }}{% if clz_is_trait %}: {% if clz_name != 'Object' %}Object + RObject + {% endif %}Debug {}{% else %} {
  #[doc(hidden)]
  #[serde(rename(serialize = "@type", deserialize = "@type"))]
  td_name: String, // {{origin_name}}
  {% if fields %}{% for field in fields %}/// {{field.description}}
  {% if field.name == 'type_' %}#[serde(rename(serialize = "type", deserialize = "type"))] {% endif %}{{field.name}}: Option<{{field.type}}>,
  {% endfor %}{% endif %}
}
{% endif %}
{% if has_trait_field %}
impl Clone for {{ clz_name }} {
  fn clone(&self) -> Self {
    let json = serde_json::to_string(self).unwrap();
    serde_json::from_str(&json[..]).unwrap()
  }
}
{% endif %}
{% if not clz_is_trait %}
impl Object for {{ clz_name }} {}
impl RObject for {{ clz_name }} {
  #[doc(hidden)] fn td_name(&self) -> &'static str { "{{ origin_name }}" }
  fn td_type(&self) -> TDType { TDType::{{ clz_name }} }
  fn to_json(&self) -> String { serde_json::to_string(self).unwrap() }
}
{% endif %}
{% if clz_super and clz_super != 'Object' and clz_super != 'TlObject' %}
{% if impl_trait_typetag %}#[typetag::serde] {% endif %}impl {{ clz_super }} for {{ clz_name }} {}
{% endif %}
{% if not is_private and not clz_is_trait %}
impl {{ clz_name }} {
  {% if has_builder_struct %}
  pub fn builder() -> {{ clz_name }}Builder {
    let instance = Self {
      td_name: "{{origin_name}}".to_string(),
      {% if fields %}{% for field in fields %}{{field.name}}: None,
      {% endfor %}{% endif %}
    };
    {{ clz_name }}Builder::new(instance)
  }
  {% endif %}
  {% if fields %}{% for field in fields %}
  pub fn {{field.name}}(&self) -> &Option<{{field.type}}> { &self.{{field.name}} }
  {% endfor %}{% endif %}
}
{% endif %}
{% if has_builder_struct %}
#[derive(Debug)]
pub struct {{ clz_name }}Builder { instance: {{ clz_name }} }

impl {{ clz_name }}Builder {
  fn new(instance: {{ clz_name }}) -> Self { Self { instance } }

  pub fn build(&self) -> {{ clz_name }} { self.instance.clone() }
  {% if fields %}{% for field in fields %}
  pub fn {{field.name}}(&mut self, {{field.name}}: {{field.type}}) -> &mut Self {
    self.instance.{{field.name}} = Some({{field.name}});
    self
  }
  {% endfor %}{% endif %}
}
{% endif %}
{% if clz_is_trait %}
{% if clz_name != 'Object' and clz_name != 'Function' %}
impl Clone for Box<{{clz_name}}> {
  fn clone(&self) -> Self {
    let json = serde_json::to_string(self).unwrap();
    serde_json::from_str(&json[..]).unwrap()
  }
}
{% endif %}
{% if has_subclasses and clz_name != 'Object' %}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, EnumString)]
pub enum TD{{clz_name}}Type {
  {% for sub in sub_classes %}{{ sub }},
  {% endfor %}
}
impl TD{{clz_name}}Type {
  pub fn of<S: AsRef<str>>(text: S) -> Option<Self> { match Self::from_str(text.as_ref()) { Ok(t) => Some(t), Err(_) => None } }
}
{% endif %}
{% endif %}
