diff --git a/client/src/ingestions.rs b/client/src/.ingestions.rs
similarity index 100%
rename from client/src/ingestions.rs
rename to client/src/.ingestions.rs
diff --git a/client/src/ingestions_util.rs b/client/src/.ingestions_util.rs
similarity index 100%
rename from client/src/ingestions_util.rs
rename to client/src/.ingestions_util.rs
diff --git a/client/src/substance_util.rs b/client/src/.substance_util.rs
similarity index 100%
rename from client/src/substance_util.rs
rename to client/src/.substance_util.rs
diff --git a/client/src/substances.rs b/client/src/.substances.rs
similarity index 100%
rename from client/src/substances.rs
rename to client/src/.substances.rs
diff --git a/client/src/drugs/drug_schema.rs b/client/src/drugs/drug_schema.rs
new file mode 100644
index 0000000..67e88c0
--- /dev/null
+++ b/client/src/drugs/drug_schema.rs
@@ -0,0 +1,3887 @@
+#![allow(clippy::redundant_closure_call)]
+#![allow(clippy::needless_lifetimes)]
+#![allow(clippy::match_single_binding)]
+#![allow(clippy::clone_on_copy)]
+
+use serde::{Deserialize, Serialize};
+
+#[doc = r" Error types."]
+pub mod error {
+    #[doc = r" Error from a TryFrom or FromStr implementation."]
+    pub struct ConversionError(std::borrow::Cow<'static, str>);
+    impl std::error::Error for ConversionError {}
+    impl std::fmt::Display for ConversionError {
+        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+            std::fmt::Display::fmt(&self.0, f)
+        }
+    }
+    impl std::fmt::Debug for ConversionError {
+        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+            std::fmt::Debug::fmt(&self.0, f)
+        }
+    }
+    impl From<&'static str> for ConversionError {
+        fn from(value: &'static str) -> Self {
+            Self(value.into())
+        }
+    }
+    impl From<String> for ConversionError {
+        fn from(value: String) -> Self {
+            Self(value.into())
+        }
+    }
+}
+#[doc = "Category"]
+#[doc = r""]
+#[doc = r" <details><summary>JSON schema</summary>"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = "  \"title\": \"Category\","]
+#[doc = "  \"type\": \"string\","]
+#[doc = "  \"enum\": ["]
+#[doc = "    \"depressant\","]
+#[doc = "    \"habit-forming\","]
+#[doc = "    \"tentative\","]
+#[doc = "    \"research-chemical\","]
+#[doc = "    \"psychedelic\","]
+#[doc = "    \"stimulant\","]
+#[doc = "    \"dissociative\","]
+#[doc = "    \"inactive\","]
+#[doc = "    \"empathogen\","]
+#[doc = "    \"common\","]
+#[doc = "    \"benzodiazepine\","]
+#[doc = "    \"opioid\","]
+#[doc = "    \"supplement\","]
+#[doc = "    \"nootropic\","]
+#[doc = "    \"barbiturate\","]
+#[doc = "    \"deliriant\","]
+#[doc = "    \"ssri\""]
+#[doc = "  ]"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" </details>"]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
+pub enum Category {
+    #[serde(rename = "depressant")]
+    Depressant,
+    #[serde(rename = "habit-forming")]
+    HabitForming,
+    #[serde(rename = "tentative")]
+    Tentative,
+    #[serde(rename = "research-chemical")]
+    ResearchChemical,
+    #[serde(rename = "psychedelic")]
+    Psychedelic,
+    #[serde(rename = "stimulant")]
+    Stimulant,
+    #[serde(rename = "dissociative")]
+    Dissociative,
+    #[serde(rename = "inactive")]
+    Inactive,
+    #[serde(rename = "empathogen")]
+    Empathogen,
+    #[serde(rename = "common")]
+    Common,
+    #[serde(rename = "benzodiazepine")]
+    Benzodiazepine,
+    #[serde(rename = "opioid")]
+    Opioid,
+    #[serde(rename = "supplement")]
+    Supplement,
+    #[serde(rename = "nootropic")]
+    Nootropic,
+    #[serde(rename = "barbiturate")]
+    Barbiturate,
+    #[serde(rename = "deliriant")]
+    Deliriant,
+    #[serde(rename = "ssri")]
+    Ssri,
+}
+impl From<&Category> for Category {
+    fn from(value: &Category) -> Self {
+        value.clone()
+    }
+}
+impl ToString for Category {
+    fn to_string(&self) -> String {
+        match *self {
+            Self::Depressant => "depressant".to_string(),
+            Self::HabitForming => "habit-forming".to_string(),
+            Self::Tentative => "tentative".to_string(),
+            Self::ResearchChemical => "research-chemical".to_string(),
+            Self::Psychedelic => "psychedelic".to_string(),
+            Self::Stimulant => "stimulant".to_string(),
+            Self::Dissociative => "dissociative".to_string(),
+            Self::Inactive => "inactive".to_string(),
+            Self::Empathogen => "empathogen".to_string(),
+            Self::Common => "common".to_string(),
+            Self::Benzodiazepine => "benzodiazepine".to_string(),
+            Self::Opioid => "opioid".to_string(),
+            Self::Supplement => "supplement".to_string(),
+            Self::Nootropic => "nootropic".to_string(),
+            Self::Barbiturate => "barbiturate".to_string(),
+            Self::Deliriant => "deliriant".to_string(),
+            Self::Ssri => "ssri".to_string(),
+        }
+    }
+}
+impl std::str::FromStr for Category {
+    type Err = self::error::ConversionError;
+    fn from_str(value: &str) -> Result<Self, self::error::ConversionError> {
+        match value {
+            "depressant" => Ok(Self::Depressant),
+            "habit-forming" => Ok(Self::HabitForming),
+            "tentative" => Ok(Self::Tentative),
+            "research-chemical" => Ok(Self::ResearchChemical),
+            "psychedelic" => Ok(Self::Psychedelic),
+            "stimulant" => Ok(Self::Stimulant),
+            "dissociative" => Ok(Self::Dissociative),
+            "inactive" => Ok(Self::Inactive),
+            "empathogen" => Ok(Self::Empathogen),
+            "common" => Ok(Self::Common),
+            "benzodiazepine" => Ok(Self::Benzodiazepine),
+            "opioid" => Ok(Self::Opioid),
+            "supplement" => Ok(Self::Supplement),
+            "nootropic" => Ok(Self::Nootropic),
+            "barbiturate" => Ok(Self::Barbiturate),
+            "deliriant" => Ok(Self::Deliriant),
+            "ssri" => Ok(Self::Ssri),
+            _ => Err("invalid value".into()),
+        }
+    }
+}
+impl std::convert::TryFrom<&str> for Category {
+    type Error = self::error::ConversionError;
+    fn try_from(value: &str) -> Result<Self, self::error::ConversionError> {
+        value.parse()
+    }
+}
+impl std::convert::TryFrom<&String> for Category {
+    type Error = self::error::ConversionError;
+    fn try_from(value: &String) -> Result<Self, self::error::ConversionError> {
+        value.parse()
+    }
+}
+impl std::convert::TryFrom<String> for Category {
+    type Error = self::error::ConversionError;
+    fn try_from(value: String) -> Result<Self, self::error::ConversionError> {
+        value.parse()
+    }
+}
+#[doc = "Combo"]
+#[doc = r""]
+#[doc = r" <details><summary>JSON schema</summary>"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = "  \"title\": \"Combo\","]
+#[doc = "  \"type\": \"object\","]
+#[doc = "  \"required\": ["]
+#[doc = "    \"status\""]
+#[doc = "  ],"]
+#[doc = "  \"properties\": {"]
+#[doc = "    \"note\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"sources\": {"]
+#[doc = "      \"type\": \"array\","]
+#[doc = "      \"items\": {"]
+#[doc = "        \"$ref\": \"#/definitions/SourceData\""]
+#[doc = "      }"]
+#[doc = "    },"]
+#[doc = "    \"status\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Status\""]
+#[doc = "    }"]
+#[doc = "  },"]
+#[doc = "  \"additionalProperties\": false"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" </details>"]
+#[derive(Clone, Debug, Deserialize, Serialize)]
+#[serde(deny_unknown_fields)]
+pub struct Combo {
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub note: Option<String>,
+    #[serde(default, skip_serializing_if = "Vec::is_empty")]
+    pub sources: Vec<SourceData>,
+    pub status: Status,
+}
+impl From<&Combo> for Combo {
+    fn from(value: &Combo) -> Self {
+        value.clone()
+    }
+}
+impl Combo {
+    pub fn builder() -> builder::Combo {
+        Default::default()
+    }
+}
+#[doc = "Dosage"]
+#[doc = r""]
+#[doc = r" <details><summary>JSON schema</summary>"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = "  \"title\": \"Buccal\","]
+#[doc = "  \"type\": \"object\","]
+#[doc = "  \"properties\": {"]
+#[doc = "    \"Common\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Dangerous\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Fatal\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Heavy\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Light\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Note\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Strong\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Threshold\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    }"]
+#[doc = "  },"]
+#[doc = "  \"additionalProperties\": false"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" </details>"]
+#[derive(Clone, Debug, Deserialize, Serialize)]
+#[serde(deny_unknown_fields)]
+pub struct Dosage {
+    #[serde(rename = "Common", default, skip_serializing_if = "Option::is_none")]
+    pub common: Option<String>,
+    #[serde(rename = "Dangerous", default, skip_serializing_if = "Option::is_none")]
+    pub dangerous: Option<String>,
+    #[serde(rename = "Fatal", default, skip_serializing_if = "Option::is_none")]
+    pub fatal: Option<String>,
+    #[serde(rename = "Heavy", default, skip_serializing_if = "Option::is_none")]
+    pub heavy: Option<String>,
+    #[serde(rename = "Light", default, skip_serializing_if = "Option::is_none")]
+    pub light: Option<String>,
+    #[serde(rename = "Note", default, skip_serializing_if = "Option::is_none")]
+    pub note: Option<String>,
+    #[serde(rename = "Strong", default, skip_serializing_if = "Option::is_none")]
+    pub strong: Option<String>,
+    #[serde(rename = "Threshold", default, skip_serializing_if = "Option::is_none")]
+    pub threshold: Option<String>,
+}
+impl From<&Dosage> for Dosage {
+    fn from(value: &Dosage) -> Self {
+        value.clone()
+    }
+}
+impl Dosage {
+    pub fn builder() -> builder::Dosage {
+        Default::default()
+    }
+}
+#[doc = "Dose"]
+#[doc = r""]
+#[doc = r" <details><summary>JSON schema</summary>"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = "  \"title\": \"FormattedDose\","]
+#[doc = "  \"type\": \"object\","]
+#[doc = "  \"properties\": {"]
+#[doc = "    \"Buccal\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Dried\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Dry\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Fresh\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"HBWR\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Insufflated\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Insufflated(Pure)\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Intramuscular\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Intravenous\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Morning_Glory\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Oral\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Oral(Benzedrex)\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Oral(Pure)\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Rectal\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Smoked\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Sublingual\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Transdermal\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Vapourized\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    },"]
+#[doc = "    \"Wet\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dosage\""]
+#[doc = "    }"]
+#[doc = "  },"]
+#[doc = "  \"additionalProperties\": false"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" </details>"]
+#[derive(Clone, Debug, Deserialize, Serialize)]
+#[serde(deny_unknown_fields)]
+pub struct Dose {
+    #[serde(rename = "Buccal", default, skip_serializing_if = "Option::is_none")]
+    pub buccal: Option<Dosage>,
+    #[serde(rename = "Dried", default, skip_serializing_if = "Option::is_none")]
+    pub dried: Option<Dosage>,
+    #[serde(rename = "Dry", default, skip_serializing_if = "Option::is_none")]
+    pub dry: Option<Dosage>,
+    #[serde(rename = "Fresh", default, skip_serializing_if = "Option::is_none")]
+    pub fresh: Option<Dosage>,
+    #[serde(rename = "HBWR", default, skip_serializing_if = "Option::is_none")]
+    pub hbwr: Option<Dosage>,
+    #[serde(
+        rename = "Insufflated",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub insufflated: Option<Dosage>,
+    #[serde(
+        rename = "Insufflated(Pure)",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub insufflated_pure: Option<Dosage>,
+    #[serde(
+        rename = "Intramuscular",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub intramuscular: Option<Dosage>,
+    #[serde(
+        rename = "Intravenous",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub intravenous: Option<Dosage>,
+    #[serde(
+        rename = "Morning_Glory",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub morning_glory: Option<Dosage>,
+    #[serde(rename = "Oral", default, skip_serializing_if = "Option::is_none")]
+    pub oral: Option<Dosage>,
+    #[serde(
+        rename = "Oral(Benzedrex)",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub oral_benzedrex: Option<Dosage>,
+    #[serde(
+        rename = "Oral(Pure)",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub oral_pure: Option<Dosage>,
+    #[serde(rename = "Rectal", default, skip_serializing_if = "Option::is_none")]
+    pub rectal: Option<Dosage>,
+    #[serde(rename = "Smoked", default, skip_serializing_if = "Option::is_none")]
+    pub smoked: Option<Dosage>,
+    #[serde(
+        rename = "Sublingual",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub sublingual: Option<Dosage>,
+    #[serde(
+        rename = "Transdermal",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub transdermal: Option<Dosage>,
+    #[serde(
+        rename = "Vapourized",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub vapourized: Option<Dosage>,
+    #[serde(rename = "Wet", default, skip_serializing_if = "Option::is_none")]
+    pub wet: Option<Dosage>,
+}
+impl From<&Dose> for Dose {
+    fn from(value: &Dose) -> Self {
+        value.clone()
+    }
+}
+impl Dose {
+    pub fn builder() -> builder::Dose {
+        Default::default()
+    }
+}
+#[doc = "Drug"]
+#[doc = r""]
+#[doc = r" <details><summary>JSON schema</summary>"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = "  \"title\": \"Drug\","]
+#[doc = "  \"type\": \"object\","]
+#[doc = "  \"required\": ["]
+#[doc = "    \"name\","]
+#[doc = "    \"pretty_name\","]
+#[doc = "    \"properties\""]
+#[doc = "  ],"]
+#[doc = "  \"properties\": {"]
+#[doc = "    \"aliases\": {"]
+#[doc = "      \"type\": \"array\","]
+#[doc = "      \"items\": {"]
+#[doc = "        \"type\": \"string\""]
+#[doc = "      }"]
+#[doc = "    },"]
+#[doc = "    \"categories\": {"]
+#[doc = "      \"type\": \"array\","]
+#[doc = "      \"items\": {"]
+#[doc = "        \"$ref\": \"#/definitions/Category\""]
+#[doc = "      }"]
+#[doc = "    },"]
+#[doc = "    \"combos\": {"]
+#[doc = "      \"type\": \"object\","]
+#[doc = "      \"properties\": {"]
+#[doc = "        \"2c-t-x\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"2c-x\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"5-meo-xxt\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"alcohol\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"amphetamines\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"amt\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"benzodiazepines\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"caffeine\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"cannabis\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"cocaine\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"dextromethorphan\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"diphenhydramine\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"dmt\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"dox\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"ghb/gbl\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"ketamine\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"lithium\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"lsd\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"maois\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"mdma\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"mephedrone\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"mescaline\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"mushrooms\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"mxe\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"nbomes\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"nitrous\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"opioids\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"pcp\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"ssris\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        },"]
+#[doc = "        \"tramadol\": {"]
+#[doc = "          \"$ref\": \"#/definitions/Combo\""]
+#[doc = "        }"]
+#[doc = "      },"]
+#[doc = "      \"additionalProperties\": false"]
+#[doc = "    },"]
+#[doc = "    \"dose_note\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"formatted_aftereffects\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Duration\""]
+#[doc = "    },"]
+#[doc = "    \"formatted_dose\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Dose\""]
+#[doc = "    },"]
+#[doc = "    \"formatted_duration\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Duration\""]
+#[doc = "    },"]
+#[doc = "    \"formatted_effects\": {"]
+#[doc = "      \"type\": \"array\","]
+#[doc = "      \"items\": {"]
+#[doc = "        \"type\": \"string\""]
+#[doc = "      }"]
+#[doc = "    },"]
+#[doc = "    \"formatted_onset\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Duration\""]
+#[doc = "    },"]
+#[doc = "    \"links\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Links\""]
+#[doc = "    },"]
+#[doc = "    \"name\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"pretty_name\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"properties\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Properties\""]
+#[doc = "    },"]
+#[doc = "    \"pweffects\": {"]
+#[doc = "      \"type\": \"object\","]
+#[doc = "      \"additionalProperties\": {"]
+#[doc = "        \"type\": \"string\","]
+#[doc = "        \"format\": \"uri\""]
+#[doc = "      }"]
+#[doc = "    },"]
+#[doc = "    \"sources\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Sources\""]
+#[doc = "    }"]
+#[doc = "  },"]
+#[doc = "  \"additionalProperties\": false"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" </details>"]
+#[derive(Clone, Debug, Deserialize, Serialize)]
+#[serde(deny_unknown_fields)]
+pub struct Drug {
+    #[serde(default, skip_serializing_if = "Vec::is_empty")]
+    pub aliases: Vec<String>,
+    #[serde(default, skip_serializing_if = "Vec::is_empty")]
+    pub categories: Vec<Category>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub combos: Option<DrugCombos>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub dose_note: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub formatted_aftereffects: Option<Duration>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub formatted_dose: Option<Dose>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub formatted_duration: Option<Duration>,
+    #[serde(default, skip_serializing_if = "Vec::is_empty")]
+    pub formatted_effects: Vec<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub formatted_onset: Option<Duration>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub links: Option<Links>,
+    pub name: String,
+    pub pretty_name: String,
+    pub properties: Properties,
+    #[serde(default, skip_serializing_if = "std::collections::HashMap::is_empty")]
+    pub pweffects: std::collections::HashMap<String, String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub sources: Option<Sources>,
+}
+impl From<&Drug> for Drug {
+    fn from(value: &Drug) -> Self {
+        value.clone()
+    }
+}
+impl Drug {
+    pub fn builder() -> builder::Drug {
+        Default::default()
+    }
+}
+#[doc = "DrugCombos"]
+#[doc = r""]
+#[doc = r" <details><summary>JSON schema</summary>"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = "  \"type\": \"object\","]
+#[doc = "  \"properties\": {"]
+#[doc = "    \"2c-t-x\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"2c-x\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"5-meo-xxt\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"alcohol\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"amphetamines\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"amt\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"benzodiazepines\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"caffeine\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"cannabis\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"cocaine\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"dextromethorphan\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"diphenhydramine\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"dmt\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"dox\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"ghb/gbl\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"ketamine\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"lithium\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"lsd\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"maois\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"mdma\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"mephedrone\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"mescaline\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"mushrooms\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"mxe\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"nbomes\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"nitrous\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"opioids\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"pcp\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"ssris\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    },"]
+#[doc = "    \"tramadol\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Combo\""]
+#[doc = "    }"]
+#[doc = "  },"]
+#[doc = "  \"additionalProperties\": false"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" </details>"]
+#[derive(Clone, Debug, Deserialize, Serialize)]
+#[serde(deny_unknown_fields)]
+pub struct DrugCombos {
+    #[serde(rename = "2c-t-x", default, skip_serializing_if = "Option::is_none")]
+    pub _2c_t_x: Option<Combo>,
+    #[serde(rename = "2c-x", default, skip_serializing_if = "Option::is_none")]
+    pub _2c_x: Option<Combo>,
+    #[serde(rename = "5-meo-xxt", default, skip_serializing_if = "Option::is_none")]
+    pub _5_meo_xxt: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub alcohol: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub amphetamines: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub amt: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub benzodiazepines: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub caffeine: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub cannabis: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub cocaine: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub dextromethorphan: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub diphenhydramine: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub dmt: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub dox: Option<Combo>,
+    #[serde(rename = "ghb/gbl", default, skip_serializing_if = "Option::is_none")]
+    pub ghb_gbl: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub ketamine: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub lithium: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub lsd: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub maois: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub mdma: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub mephedrone: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub mescaline: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub mushrooms: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub mxe: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub nbomes: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub nitrous: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub opioids: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub pcp: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub ssris: Option<Combo>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub tramadol: Option<Combo>,
+}
+impl From<&DrugCombos> for DrugCombos {
+    fn from(value: &DrugCombos) -> Self {
+        value.clone()
+    }
+}
+impl DrugCombos {
+    pub fn builder() -> builder::DrugCombos {
+        Default::default()
+    }
+}
+#[doc = "Duration"]
+#[doc = r""]
+#[doc = r" <details><summary>JSON schema</summary>"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = "  \"title\": \"Formatted\","]
+#[doc = "  \"type\": \"object\","]
+#[doc = "  \"properties\": {"]
+#[doc = "    \"Buccal\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Insufflated\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Insufflated_IR\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Insufflated_XR\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Intramuscular\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Intravenous\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Metabolites\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Oral\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Oral_ER\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Oral_IR\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Oral_MAOI\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Parent\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Rectal\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Smoked\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Sublingual\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Transdermal\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"Vapourized\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"_unit\": {"]
+#[doc = "      \"$ref\": \"#/definitions/Unit\""]
+#[doc = "    },"]
+#[doc = "    \"value\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    }"]
+#[doc = "  },"]
+#[doc = "  \"additionalProperties\": false"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" </details>"]
+#[derive(Clone, Debug, Deserialize, Serialize)]
+#[serde(deny_unknown_fields)]
+pub struct Duration {
+    #[serde(rename = "Buccal", default, skip_serializing_if = "Option::is_none")]
+    pub buccal: Option<String>,
+    #[serde(
+        rename = "Insufflated",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub insufflated: Option<String>,
+    #[serde(
+        rename = "Insufflated_IR",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub insufflated_ir: Option<String>,
+    #[serde(
+        rename = "Insufflated_XR",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub insufflated_xr: Option<String>,
+    #[serde(
+        rename = "Intramuscular",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub intramuscular: Option<String>,
+    #[serde(
+        rename = "Intravenous",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub intravenous: Option<String>,
+    #[serde(
+        rename = "Metabolites",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub metabolites: Option<String>,
+    #[serde(rename = "Oral", default, skip_serializing_if = "Option::is_none")]
+    pub oral: Option<String>,
+    #[serde(rename = "Oral_ER", default, skip_serializing_if = "Option::is_none")]
+    pub oral_er: Option<String>,
+    #[serde(rename = "Oral_IR", default, skip_serializing_if = "Option::is_none")]
+    pub oral_ir: Option<String>,
+    #[serde(rename = "Oral_MAOI", default, skip_serializing_if = "Option::is_none")]
+    pub oral_maoi: Option<String>,
+    #[serde(rename = "Parent", default, skip_serializing_if = "Option::is_none")]
+    pub parent: Option<String>,
+    #[serde(rename = "Rectal", default, skip_serializing_if = "Option::is_none")]
+    pub rectal: Option<String>,
+    #[serde(rename = "Smoked", default, skip_serializing_if = "Option::is_none")]
+    pub smoked: Option<String>,
+    #[serde(
+        rename = "Sublingual",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub sublingual: Option<String>,
+    #[serde(
+        rename = "Transdermal",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub transdermal: Option<String>,
+    #[serde(rename = "_unit", default, skip_serializing_if = "Option::is_none")]
+    pub unit: Option<Unit>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub value: Option<String>,
+    #[serde(
+        rename = "Vapourized",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub vapourized: Option<String>,
+}
+impl From<&Duration> for Duration {
+    fn from(value: &Duration) -> Self {
+        value.clone()
+    }
+}
+impl Duration {
+    pub fn builder() -> builder::Duration {
+        Default::default()
+    }
+}
+#[doc = "Links"]
+#[doc = r""]
+#[doc = r" <details><summary>JSON schema</summary>"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = "  \"title\": \"Links\","]
+#[doc = "  \"type\": \"object\","]
+#[doc = "  \"required\": ["]
+#[doc = "    \"experiences\""]
+#[doc = "  ],"]
+#[doc = "  \"properties\": {"]
+#[doc = "    \"experiences\": {"]
+#[doc = "      \"type\": \"string\","]
+#[doc = "      \"format\": \"uri\""]
+#[doc = "    },"]
+#[doc = "    \"pihkal\": {"]
+#[doc = "      \"type\": \"string\","]
+#[doc = "      \"format\": \"uri\""]
+#[doc = "    },"]
+#[doc = "    \"tihkal\": {"]
+#[doc = "      \"type\": \"string\","]
+#[doc = "      \"format\": \"uri\""]
+#[doc = "    }"]
+#[doc = "  },"]
+#[doc = "  \"additionalProperties\": false"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" </details>"]
+#[derive(Clone, Debug, Deserialize, Serialize)]
+#[serde(deny_unknown_fields)]
+pub struct Links {
+    pub experiences: String,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub pihkal: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub tihkal: Option<String>,
+}
+impl From<&Links> for Links {
+    fn from(value: &Links) -> Self {
+        value.clone()
+    }
+}
+impl Links {
+    pub fn builder() -> builder::Links {
+        Default::default()
+    }
+}
+#[doc = "Properties"]
+#[doc = r""]
+#[doc = r" <details><summary>JSON schema</summary>"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = "  \"title\": \"Properties\","]
+#[doc = "  \"type\": \"object\","]
+#[doc = "  \"properties\": {"]
+#[doc = "    \"Oral\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"adverse-effects\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"after-effects\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"aliases\": {"]
+#[doc = "      \"type\": \"array\","]
+#[doc = "      \"items\": {"]
+#[doc = "        \"type\": \"string\""]
+#[doc = "      }"]
+#[doc = "    },"]
+#[doc = "    \"avoid\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"bioavailability\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"calculator\": {"]
+#[doc = "      \"type\": \"string\","]
+#[doc = "      \"format\": \"uri\""]
+#[doc = "    },"]
+#[doc = "    \"categories\": {"]
+#[doc = "      \"type\": \"array\","]
+#[doc = "      \"items\": {"]
+#[doc = "        \"$ref\": \"#/definitions/Category\""]
+#[doc = "      }"]
+#[doc = "    },"]
+#[doc = "    \"chart\": {"]
+#[doc = "      \"type\": \"string\","]
+#[doc = "      \"format\": \"uri\""]
+#[doc = "    },"]
+#[doc = "    \"chemistry\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"comeup\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"contraindications\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"detection\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"dose\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"dose_to_diazepam\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"duration\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"effects\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"experiences\": {"]
+#[doc = "      \"type\": \"string\","]
+#[doc = "      \"format\": \"uri\""]
+#[doc = "    },"]
+#[doc = "    \"general-advice\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"half-life\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"legal\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"marquis\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"mdma\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"molecule\": {"]
+#[doc = "      \"type\": \"string\","]
+#[doc = "      \"format\": \"uri\""]
+#[doc = "    },"]
+#[doc = "    \"note\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"obtain\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"onset\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"overdose-symptoms\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"pharmacodynamics\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"pharmacokinetics\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"pharmacology\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"potentiators\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"risks\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"side-effects\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"summary\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"test-kits\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"tolerance\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"vaporization\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"warning\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"wiki\": {"]
+#[doc = "      \"type\": \"string\","]
+#[doc = "      \"format\": \"uri\""]
+#[doc = "    }"]
+#[doc = "  },"]
+#[doc = "  \"additionalProperties\": false"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" </details>"]
+#[derive(Clone, Debug, Deserialize, Serialize)]
+#[serde(deny_unknown_fields)]
+pub struct Properties {
+    #[serde(
+        rename = "adverse-effects",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub adverse_effects: Option<String>,
+    #[serde(
+        rename = "after-effects",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub after_effects: Option<String>,
+    #[serde(default, skip_serializing_if = "Vec::is_empty")]
+    pub aliases: Vec<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub avoid: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub bioavailability: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub calculator: Option<String>,
+    #[serde(default, skip_serializing_if = "Vec::is_empty")]
+    pub categories: Vec<Category>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub chart: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub chemistry: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub comeup: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub contraindications: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub detection: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub dose: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub dose_to_diazepam: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub duration: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub effects: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub experiences: Option<String>,
+    #[serde(
+        rename = "general-advice",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub general_advice: Option<String>,
+    #[serde(rename = "half-life", default, skip_serializing_if = "Option::is_none")]
+    pub half_life: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub legal: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub marquis: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub mdma: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub molecule: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub note: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub obtain: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub onset: Option<String>,
+    #[serde(rename = "Oral", default, skip_serializing_if = "Option::is_none")]
+    pub oral: Option<String>,
+    #[serde(
+        rename = "overdose-symptoms",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub overdose_symptoms: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub pharmacodynamics: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub pharmacokinetics: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub pharmacology: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub potentiators: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub risks: Option<String>,
+    #[serde(
+        rename = "side-effects",
+        default,
+        skip_serializing_if = "Option::is_none"
+    )]
+    pub side_effects: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub summary: Option<String>,
+    #[serde(rename = "test-kits", default, skip_serializing_if = "Option::is_none")]
+    pub test_kits: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub tolerance: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub vaporization: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub warning: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub wiki: Option<String>,
+}
+impl From<&Properties> for Properties {
+    fn from(value: &Properties) -> Self {
+        value.clone()
+    }
+}
+impl Properties {
+    pub fn builder() -> builder::Properties {
+        Default::default()
+    }
+}
+#[doc = "SourceData"]
+#[doc = r""]
+#[doc = r" <details><summary>JSON schema</summary>"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = "  \"title\": \"SourceData\","]
+#[doc = "  \"type\": \"object\","]
+#[doc = "  \"properties\": {"]
+#[doc = "    \"author\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"title\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    },"]
+#[doc = "    \"url\": {"]
+#[doc = "      \"type\": \"string\""]
+#[doc = "    }"]
+#[doc = "  },"]
+#[doc = "  \"additionalProperties\": false"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" </details>"]
+#[derive(Clone, Debug, Deserialize, Serialize)]
+#[serde(deny_unknown_fields)]
+pub struct SourceData {
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub author: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub title: Option<String>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub url: Option<String>,
+}
+impl From<&SourceData> for SourceData {
+    fn from(value: &SourceData) -> Self {
+        value.clone()
+    }
+}
+impl SourceData {
+    pub fn builder() -> builder::SourceData {
+        Default::default()
+    }
+}
+#[doc = "Sources"]
+#[doc = r""]
+#[doc = r" <details><summary>JSON schema</summary>"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = "  \"title\": \"Sources\","]
+#[doc = "  \"type\": \"object\","]
+#[doc = "  \"properties\": {"]
+#[doc = "    \"_general\": {"]
+#[doc = "      \"type\": \"array\","]
+#[doc = "      \"items\": {"]
+#[doc = "        \"type\": \"string\""]
+#[doc = "      }"]
+#[doc = "    },"]
+#[doc = "    \"bioavailability\": {"]
+#[doc = "      \"type\": \"array\","]
+#[doc = "      \"items\": {"]
+#[doc = "        \"type\": \"string\","]
+#[doc = "        \"format\": \"uri\""]
+#[doc = "      }"]
+#[doc = "    },"]
+#[doc = "    \"dose\": {"]
+#[doc = "      \"type\": \"array\","]
+#[doc = "      \"items\": {"]
+#[doc = "        \"type\": \"string\","]
+#[doc = "        \"format\": \"uri\""]
+#[doc = "      }"]
+#[doc = "    },"]
+#[doc = "    \"duration\": {"]
+#[doc = "      \"type\": \"array\","]
+#[doc = "      \"items\": {"]
+#[doc = "        \"type\": \"string\","]
+#[doc = "        \"format\": \"uri\""]
+#[doc = "      }"]
+#[doc = "    },"]
+#[doc = "    \"legality\": {"]
+#[doc = "      \"type\": \"array\","]
+#[doc = "      \"items\": {"]
+#[doc = "        \"type\": \"string\","]
+#[doc = "        \"format\": \"uri\""]
+#[doc = "      }"]
+#[doc = "    },"]
+#[doc = "    \"onset\": {"]
+#[doc = "      \"type\": \"array\","]
+#[doc = "      \"items\": {"]
+#[doc = "        \"type\": \"string\""]
+#[doc = "      }"]
+#[doc = "    }"]
+#[doc = "  },"]
+#[doc = "  \"additionalProperties\": false"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" </details>"]
+#[derive(Clone, Debug, Deserialize, Serialize)]
+#[serde(deny_unknown_fields)]
+pub struct Sources {
+    #[serde(default, skip_serializing_if = "Vec::is_empty")]
+    pub bioavailability: Vec<String>,
+    #[serde(default, skip_serializing_if = "Vec::is_empty")]
+    pub dose: Vec<String>,
+    #[serde(default, skip_serializing_if = "Vec::is_empty")]
+    pub duration: Vec<String>,
+    #[serde(rename = "_general", default, skip_serializing_if = "Vec::is_empty")]
+    pub general: Vec<String>,
+    #[serde(default, skip_serializing_if = "Vec::is_empty")]
+    pub legality: Vec<String>,
+    #[serde(default, skip_serializing_if = "Vec::is_empty")]
+    pub onset: Vec<String>,
+}
+impl From<&Sources> for Sources {
+    fn from(value: &Sources) -> Self {
+        value.clone()
+    }
+}
+impl Sources {
+    pub fn builder() -> builder::Sources {
+        Default::default()
+    }
+}
+#[doc = "Status"]
+#[doc = r""]
+#[doc = r" <details><summary>JSON schema</summary>"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = "  \"title\": \"Status\","]
+#[doc = "  \"type\": \"string\","]
+#[doc = "  \"enum\": ["]
+#[doc = "    \"Low Risk & Decrease\","]
+#[doc = "    \"Dangerous\","]
+#[doc = "    \"Low Risk & No Synergy\","]
+#[doc = "    \"Caution\","]
+#[doc = "    \"Unsafe\","]
+#[doc = "    \"Low Risk & Synergy\""]
+#[doc = "  ]"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" </details>"]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
+pub enum Status {
+    #[serde(rename = "Low Risk & Decrease")]
+    LowRiskDecrease,
+    Dangerous,
+    #[serde(rename = "Low Risk & No Synergy")]
+    LowRiskNoSynergy,
+    Caution,
+    Unsafe,
+    #[serde(rename = "Low Risk & Synergy")]
+    LowRiskSynergy,
+}
+impl From<&Status> for Status {
+    fn from(value: &Status) -> Self {
+        value.clone()
+    }
+}
+impl ToString for Status {
+    fn to_string(&self) -> String {
+        match *self {
+            Self::LowRiskDecrease => "Low Risk & Decrease".to_string(),
+            Self::Dangerous => "Dangerous".to_string(),
+            Self::LowRiskNoSynergy => "Low Risk & No Synergy".to_string(),
+            Self::Caution => "Caution".to_string(),
+            Self::Unsafe => "Unsafe".to_string(),
+            Self::LowRiskSynergy => "Low Risk & Synergy".to_string(),
+        }
+    }
+}
+impl std::str::FromStr for Status {
+    type Err = self::error::ConversionError;
+    fn from_str(value: &str) -> Result<Self, self::error::ConversionError> {
+        match value {
+            "Low Risk & Decrease" => Ok(Self::LowRiskDecrease),
+            "Dangerous" => Ok(Self::Dangerous),
+            "Low Risk & No Synergy" => Ok(Self::LowRiskNoSynergy),
+            "Caution" => Ok(Self::Caution),
+            "Unsafe" => Ok(Self::Unsafe),
+            "Low Risk & Synergy" => Ok(Self::LowRiskSynergy),
+            _ => Err("invalid value".into()),
+        }
+    }
+}
+impl std::convert::TryFrom<&str> for Status {
+    type Error = self::error::ConversionError;
+    fn try_from(value: &str) -> Result<Self, self::error::ConversionError> {
+        value.parse()
+    }
+}
+impl std::convert::TryFrom<&String> for Status {
+    type Error = self::error::ConversionError;
+    fn try_from(value: &String) -> Result<Self, self::error::ConversionError> {
+        value.parse()
+    }
+}
+impl std::convert::TryFrom<String> for Status {
+    type Error = self::error::ConversionError;
+    fn try_from(value: String) -> Result<Self, self::error::ConversionError> {
+        value.parse()
+    }
+}
+#[doc = "Unit"]
+#[doc = r""]
+#[doc = r" <details><summary>JSON schema</summary>"]
+#[doc = r""]
+#[doc = r" ```json"]
+#[doc = "{"]
+#[doc = "  \"title\": \"Unit\","]
+#[doc = "  \"type\": \"string\","]
+#[doc = "  \"enum\": ["]
+#[doc = "    \"hours\","]
+#[doc = "    \"minutes\""]
+#[doc = "  ]"]
+#[doc = "}"]
+#[doc = r" ```"]
+#[doc = r" </details>"]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
+pub enum Unit {
+    #[serde(rename = "hours")]
+    Hours,
+    #[serde(rename = "minutes")]
+    Minutes,
+}
+impl From<&Unit> for Unit {
+    fn from(value: &Unit) -> Self {
+        value.clone()
+    }
+}
+impl ToString for Unit {
+    fn to_string(&self) -> String {
+        match *self {
+            Self::Hours => "hours".to_string(),
+            Self::Minutes => "minutes".to_string(),
+        }
+    }
+}
+impl std::str::FromStr for Unit {
+    type Err = self::error::ConversionError;
+    fn from_str(value: &str) -> Result<Self, self::error::ConversionError> {
+        match value {
+            "hours" => Ok(Self::Hours),
+            "minutes" => Ok(Self::Minutes),
+            _ => Err("invalid value".into()),
+        }
+    }
+}
+impl std::convert::TryFrom<&str> for Unit {
+    type Error = self::error::ConversionError;
+    fn try_from(value: &str) -> Result<Self, self::error::ConversionError> {
+        value.parse()
+    }
+}
+impl std::convert::TryFrom<&String> for Unit {
+    type Error = self::error::ConversionError;
+    fn try_from(value: &String) -> Result<Self, self::error::ConversionError> {
+        value.parse()
+    }
+}
+impl std::convert::TryFrom<String> for Unit {
+    type Error = self::error::ConversionError;
+    fn try_from(value: String) -> Result<Self, self::error::ConversionError> {
+        value.parse()
+    }
+}
+#[doc = r" Types for composing complex structures."]
+pub mod builder {
+    #[derive(Clone, Debug)]
+    pub struct Combo {
+        note: Result<Option<String>, String>,
+        sources: Result<Vec<super::SourceData>, String>,
+        status: Result<super::Status, String>,
+    }
+    impl Default for Combo {
+        fn default() -> Self {
+            Self {
+                note: Ok(Default::default()),
+                sources: Ok(Default::default()),
+                status: Err("no value supplied for status".to_string()),
+            }
+        }
+    }
+    impl Combo {
+        pub fn note<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.note = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for note: {}", e));
+            self
+        }
+        pub fn sources<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Vec<super::SourceData>>,
+            T::Error: std::fmt::Display,
+        {
+            self.sources = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for sources: {}", e));
+            self
+        }
+        pub fn status<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<super::Status>,
+            T::Error: std::fmt::Display,
+        {
+            self.status = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for status: {}", e));
+            self
+        }
+    }
+    impl std::convert::TryFrom<Combo> for super::Combo {
+        type Error = super::error::ConversionError;
+        fn try_from(value: Combo) -> Result<Self, super::error::ConversionError> {
+            Ok(Self {
+                note: value.note?,
+                sources: value.sources?,
+                status: value.status?,
+            })
+        }
+    }
+    impl From<super::Combo> for Combo {
+        fn from(value: super::Combo) -> Self {
+            Self {
+                note: Ok(value.note),
+                sources: Ok(value.sources),
+                status: Ok(value.status),
+            }
+        }
+    }
+    #[derive(Clone, Debug)]
+    pub struct Dosage {
+        common: Result<Option<String>, String>,
+        dangerous: Result<Option<String>, String>,
+        fatal: Result<Option<String>, String>,
+        heavy: Result<Option<String>, String>,
+        light: Result<Option<String>, String>,
+        note: Result<Option<String>, String>,
+        strong: Result<Option<String>, String>,
+        threshold: Result<Option<String>, String>,
+    }
+    impl Default for Dosage {
+        fn default() -> Self {
+            Self {
+                common: Ok(Default::default()),
+                dangerous: Ok(Default::default()),
+                fatal: Ok(Default::default()),
+                heavy: Ok(Default::default()),
+                light: Ok(Default::default()),
+                note: Ok(Default::default()),
+                strong: Ok(Default::default()),
+                threshold: Ok(Default::default()),
+            }
+        }
+    }
+    impl Dosage {
+        pub fn common<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.common = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for common: {}", e));
+            self
+        }
+        pub fn dangerous<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.dangerous = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for dangerous: {}", e));
+            self
+        }
+        pub fn fatal<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.fatal = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for fatal: {}", e));
+            self
+        }
+        pub fn heavy<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.heavy = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for heavy: {}", e));
+            self
+        }
+        pub fn light<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.light = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for light: {}", e));
+            self
+        }
+        pub fn note<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.note = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for note: {}", e));
+            self
+        }
+        pub fn strong<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.strong = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for strong: {}", e));
+            self
+        }
+        pub fn threshold<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.threshold = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for threshold: {}", e));
+            self
+        }
+    }
+    impl std::convert::TryFrom<Dosage> for super::Dosage {
+        type Error = super::error::ConversionError;
+        fn try_from(value: Dosage) -> Result<Self, super::error::ConversionError> {
+            Ok(Self {
+                common: value.common?,
+                dangerous: value.dangerous?,
+                fatal: value.fatal?,
+                heavy: value.heavy?,
+                light: value.light?,
+                note: value.note?,
+                strong: value.strong?,
+                threshold: value.threshold?,
+            })
+        }
+    }
+    impl From<super::Dosage> for Dosage {
+        fn from(value: super::Dosage) -> Self {
+            Self {
+                common: Ok(value.common),
+                dangerous: Ok(value.dangerous),
+                fatal: Ok(value.fatal),
+                heavy: Ok(value.heavy),
+                light: Ok(value.light),
+                note: Ok(value.note),
+                strong: Ok(value.strong),
+                threshold: Ok(value.threshold),
+            }
+        }
+    }
+    #[derive(Clone, Debug)]
+    pub struct Dose {
+        buccal: Result<Option<super::Dosage>, String>,
+        dried: Result<Option<super::Dosage>, String>,
+        dry: Result<Option<super::Dosage>, String>,
+        fresh: Result<Option<super::Dosage>, String>,
+        hbwr: Result<Option<super::Dosage>, String>,
+        insufflated: Result<Option<super::Dosage>, String>,
+        insufflated_pure: Result<Option<super::Dosage>, String>,
+        intramuscular: Result<Option<super::Dosage>, String>,
+        intravenous: Result<Option<super::Dosage>, String>,
+        morning_glory: Result<Option<super::Dosage>, String>,
+        oral: Result<Option<super::Dosage>, String>,
+        oral_benzedrex: Result<Option<super::Dosage>, String>,
+        oral_pure: Result<Option<super::Dosage>, String>,
+        rectal: Result<Option<super::Dosage>, String>,
+        smoked: Result<Option<super::Dosage>, String>,
+        sublingual: Result<Option<super::Dosage>, String>,
+        transdermal: Result<Option<super::Dosage>, String>,
+        vapourized: Result<Option<super::Dosage>, String>,
+        wet: Result<Option<super::Dosage>, String>,
+    }
+    impl Default for Dose {
+        fn default() -> Self {
+            Self {
+                buccal: Ok(Default::default()),
+                dried: Ok(Default::default()),
+                dry: Ok(Default::default()),
+                fresh: Ok(Default::default()),
+                hbwr: Ok(Default::default()),
+                insufflated: Ok(Default::default()),
+                insufflated_pure: Ok(Default::default()),
+                intramuscular: Ok(Default::default()),
+                intravenous: Ok(Default::default()),
+                morning_glory: Ok(Default::default()),
+                oral: Ok(Default::default()),
+                oral_benzedrex: Ok(Default::default()),
+                oral_pure: Ok(Default::default()),
+                rectal: Ok(Default::default()),
+                smoked: Ok(Default::default()),
+                sublingual: Ok(Default::default()),
+                transdermal: Ok(Default::default()),
+                vapourized: Ok(Default::default()),
+                wet: Ok(Default::default()),
+            }
+        }
+    }
+    impl Dose {
+        pub fn buccal<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.buccal = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for buccal: {}", e));
+            self
+        }
+        pub fn dried<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.dried = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for dried: {}", e));
+            self
+        }
+        pub fn dry<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.dry = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for dry: {}", e));
+            self
+        }
+        pub fn fresh<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.fresh = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for fresh: {}", e));
+            self
+        }
+        pub fn hbwr<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.hbwr = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for hbwr: {}", e));
+            self
+        }
+        pub fn insufflated<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.insufflated = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for insufflated: {}", e));
+            self
+        }
+        pub fn insufflated_pure<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.insufflated_pure = value.try_into().map_err(|e| {
+                format!(
+                    "error converting supplied value for insufflated_pure: {}",
+                    e
+                )
+            });
+            self
+        }
+        pub fn intramuscular<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.intramuscular = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for intramuscular: {}", e));
+            self
+        }
+        pub fn intravenous<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.intravenous = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for intravenous: {}", e));
+            self
+        }
+        pub fn morning_glory<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.morning_glory = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for morning_glory: {}", e));
+            self
+        }
+        pub fn oral<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.oral = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for oral: {}", e));
+            self
+        }
+        pub fn oral_benzedrex<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.oral_benzedrex = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for oral_benzedrex: {}", e));
+            self
+        }
+        pub fn oral_pure<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.oral_pure = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for oral_pure: {}", e));
+            self
+        }
+        pub fn rectal<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.rectal = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for rectal: {}", e));
+            self
+        }
+        pub fn smoked<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.smoked = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for smoked: {}", e));
+            self
+        }
+        pub fn sublingual<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.sublingual = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for sublingual: {}", e));
+            self
+        }
+        pub fn transdermal<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.transdermal = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for transdermal: {}", e));
+            self
+        }
+        pub fn vapourized<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.vapourized = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for vapourized: {}", e));
+            self
+        }
+        pub fn wet<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dosage>>,
+            T::Error: std::fmt::Display,
+        {
+            self.wet = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for wet: {}", e));
+            self
+        }
+    }
+    impl std::convert::TryFrom<Dose> for super::Dose {
+        type Error = super::error::ConversionError;
+        fn try_from(value: Dose) -> Result<Self, super::error::ConversionError> {
+            Ok(Self {
+                buccal: value.buccal?,
+                dried: value.dried?,
+                dry: value.dry?,
+                fresh: value.fresh?,
+                hbwr: value.hbwr?,
+                insufflated: value.insufflated?,
+                insufflated_pure: value.insufflated_pure?,
+                intramuscular: value.intramuscular?,
+                intravenous: value.intravenous?,
+                morning_glory: value.morning_glory?,
+                oral: value.oral?,
+                oral_benzedrex: value.oral_benzedrex?,
+                oral_pure: value.oral_pure?,
+                rectal: value.rectal?,
+                smoked: value.smoked?,
+                sublingual: value.sublingual?,
+                transdermal: value.transdermal?,
+                vapourized: value.vapourized?,
+                wet: value.wet?,
+            })
+        }
+    }
+    impl From<super::Dose> for Dose {
+        fn from(value: super::Dose) -> Self {
+            Self {
+                buccal: Ok(value.buccal),
+                dried: Ok(value.dried),
+                dry: Ok(value.dry),
+                fresh: Ok(value.fresh),
+                hbwr: Ok(value.hbwr),
+                insufflated: Ok(value.insufflated),
+                insufflated_pure: Ok(value.insufflated_pure),
+                intramuscular: Ok(value.intramuscular),
+                intravenous: Ok(value.intravenous),
+                morning_glory: Ok(value.morning_glory),
+                oral: Ok(value.oral),
+                oral_benzedrex: Ok(value.oral_benzedrex),
+                oral_pure: Ok(value.oral_pure),
+                rectal: Ok(value.rectal),
+                smoked: Ok(value.smoked),
+                sublingual: Ok(value.sublingual),
+                transdermal: Ok(value.transdermal),
+                vapourized: Ok(value.vapourized),
+                wet: Ok(value.wet),
+            }
+        }
+    }
+    #[derive(Clone, Debug)]
+    pub struct Drug {
+        aliases: Result<Vec<String>, String>,
+        categories: Result<Vec<super::Category>, String>,
+        combos: Result<Option<super::DrugCombos>, String>,
+        dose_note: Result<Option<String>, String>,
+        formatted_aftereffects: Result<Option<super::Duration>, String>,
+        formatted_dose: Result<Option<super::Dose>, String>,
+        formatted_duration: Result<Option<super::Duration>, String>,
+        formatted_effects: Result<Vec<String>, String>,
+        formatted_onset: Result<Option<super::Duration>, String>,
+        links: Result<Option<super::Links>, String>,
+        name: Result<String, String>,
+        pretty_name: Result<String, String>,
+        properties: Result<super::Properties, String>,
+        pweffects: Result<std::collections::HashMap<String, String>, String>,
+        sources: Result<Option<super::Sources>, String>,
+    }
+    impl Default for Drug {
+        fn default() -> Self {
+            Self {
+                aliases: Ok(Default::default()),
+                categories: Ok(Default::default()),
+                combos: Ok(Default::default()),
+                dose_note: Ok(Default::default()),
+                formatted_aftereffects: Ok(Default::default()),
+                formatted_dose: Ok(Default::default()),
+                formatted_duration: Ok(Default::default()),
+                formatted_effects: Ok(Default::default()),
+                formatted_onset: Ok(Default::default()),
+                links: Ok(Default::default()),
+                name: Err("no value supplied for name".to_string()),
+                pretty_name: Err("no value supplied for pretty_name".to_string()),
+                properties: Err("no value supplied for properties".to_string()),
+                pweffects: Ok(Default::default()),
+                sources: Ok(Default::default()),
+            }
+        }
+    }
+    impl Drug {
+        pub fn aliases<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Vec<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.aliases = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for aliases: {}", e));
+            self
+        }
+        pub fn categories<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Vec<super::Category>>,
+            T::Error: std::fmt::Display,
+        {
+            self.categories = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for categories: {}", e));
+            self
+        }
+        pub fn combos<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::DrugCombos>>,
+            T::Error: std::fmt::Display,
+        {
+            self.combos = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for combos: {}", e));
+            self
+        }
+        pub fn dose_note<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.dose_note = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for dose_note: {}", e));
+            self
+        }
+        pub fn formatted_aftereffects<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Duration>>,
+            T::Error: std::fmt::Display,
+        {
+            self.formatted_aftereffects = value.try_into().map_err(|e| {
+                format!(
+                    "error converting supplied value for formatted_aftereffects: {}",
+                    e
+                )
+            });
+            self
+        }
+        pub fn formatted_dose<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Dose>>,
+            T::Error: std::fmt::Display,
+        {
+            self.formatted_dose = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for formatted_dose: {}", e));
+            self
+        }
+        pub fn formatted_duration<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Duration>>,
+            T::Error: std::fmt::Display,
+        {
+            self.formatted_duration = value.try_into().map_err(|e| {
+                format!(
+                    "error converting supplied value for formatted_duration: {}",
+                    e
+                )
+            });
+            self
+        }
+        pub fn formatted_effects<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Vec<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.formatted_effects = value.try_into().map_err(|e| {
+                format!(
+                    "error converting supplied value for formatted_effects: {}",
+                    e
+                )
+            });
+            self
+        }
+        pub fn formatted_onset<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Duration>>,
+            T::Error: std::fmt::Display,
+        {
+            self.formatted_onset = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for formatted_onset: {}", e));
+            self
+        }
+        pub fn links<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Links>>,
+            T::Error: std::fmt::Display,
+        {
+            self.links = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for links: {}", e));
+            self
+        }
+        pub fn name<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<String>,
+            T::Error: std::fmt::Display,
+        {
+            self.name = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for name: {}", e));
+            self
+        }
+        pub fn pretty_name<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<String>,
+            T::Error: std::fmt::Display,
+        {
+            self.pretty_name = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for pretty_name: {}", e));
+            self
+        }
+        pub fn properties<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<super::Properties>,
+            T::Error: std::fmt::Display,
+        {
+            self.properties = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for properties: {}", e));
+            self
+        }
+        pub fn pweffects<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<std::collections::HashMap<String, String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.pweffects = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for pweffects: {}", e));
+            self
+        }
+        pub fn sources<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Sources>>,
+            T::Error: std::fmt::Display,
+        {
+            self.sources = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for sources: {}", e));
+            self
+        }
+    }
+    impl std::convert::TryFrom<Drug> for super::Drug {
+        type Error = super::error::ConversionError;
+        fn try_from(value: Drug) -> Result<Self, super::error::ConversionError> {
+            Ok(Self {
+                aliases: value.aliases?,
+                categories: value.categories?,
+                combos: value.combos?,
+                dose_note: value.dose_note?,
+                formatted_aftereffects: value.formatted_aftereffects?,
+                formatted_dose: value.formatted_dose?,
+                formatted_duration: value.formatted_duration?,
+                formatted_effects: value.formatted_effects?,
+                formatted_onset: value.formatted_onset?,
+                links: value.links?,
+                name: value.name?,
+                pretty_name: value.pretty_name?,
+                properties: value.properties?,
+                pweffects: value.pweffects?,
+                sources: value.sources?,
+            })
+        }
+    }
+    impl From<super::Drug> for Drug {
+        fn from(value: super::Drug) -> Self {
+            Self {
+                aliases: Ok(value.aliases),
+                categories: Ok(value.categories),
+                combos: Ok(value.combos),
+                dose_note: Ok(value.dose_note),
+                formatted_aftereffects: Ok(value.formatted_aftereffects),
+                formatted_dose: Ok(value.formatted_dose),
+                formatted_duration: Ok(value.formatted_duration),
+                formatted_effects: Ok(value.formatted_effects),
+                formatted_onset: Ok(value.formatted_onset),
+                links: Ok(value.links),
+                name: Ok(value.name),
+                pretty_name: Ok(value.pretty_name),
+                properties: Ok(value.properties),
+                pweffects: Ok(value.pweffects),
+                sources: Ok(value.sources),
+            }
+        }
+    }
+    #[derive(Clone, Debug)]
+    pub struct DrugCombos {
+        _2c_t_x: Result<Option<super::Combo>, String>,
+        _2c_x: Result<Option<super::Combo>, String>,
+        _5_meo_xxt: Result<Option<super::Combo>, String>,
+        alcohol: Result<Option<super::Combo>, String>,
+        amphetamines: Result<Option<super::Combo>, String>,
+        amt: Result<Option<super::Combo>, String>,
+        benzodiazepines: Result<Option<super::Combo>, String>,
+        caffeine: Result<Option<super::Combo>, String>,
+        cannabis: Result<Option<super::Combo>, String>,
+        cocaine: Result<Option<super::Combo>, String>,
+        dextromethorphan: Result<Option<super::Combo>, String>,
+        diphenhydramine: Result<Option<super::Combo>, String>,
+        dmt: Result<Option<super::Combo>, String>,
+        dox: Result<Option<super::Combo>, String>,
+        ghb_gbl: Result<Option<super::Combo>, String>,
+        ketamine: Result<Option<super::Combo>, String>,
+        lithium: Result<Option<super::Combo>, String>,
+        lsd: Result<Option<super::Combo>, String>,
+        maois: Result<Option<super::Combo>, String>,
+        mdma: Result<Option<super::Combo>, String>,
+        mephedrone: Result<Option<super::Combo>, String>,
+        mescaline: Result<Option<super::Combo>, String>,
+        mushrooms: Result<Option<super::Combo>, String>,
+        mxe: Result<Option<super::Combo>, String>,
+        nbomes: Result<Option<super::Combo>, String>,
+        nitrous: Result<Option<super::Combo>, String>,
+        opioids: Result<Option<super::Combo>, String>,
+        pcp: Result<Option<super::Combo>, String>,
+        ssris: Result<Option<super::Combo>, String>,
+        tramadol: Result<Option<super::Combo>, String>,
+    }
+    impl Default for DrugCombos {
+        fn default() -> Self {
+            Self {
+                _2c_t_x: Ok(Default::default()),
+                _2c_x: Ok(Default::default()),
+                _5_meo_xxt: Ok(Default::default()),
+                alcohol: Ok(Default::default()),
+                amphetamines: Ok(Default::default()),
+                amt: Ok(Default::default()),
+                benzodiazepines: Ok(Default::default()),
+                caffeine: Ok(Default::default()),
+                cannabis: Ok(Default::default()),
+                cocaine: Ok(Default::default()),
+                dextromethorphan: Ok(Default::default()),
+                diphenhydramine: Ok(Default::default()),
+                dmt: Ok(Default::default()),
+                dox: Ok(Default::default()),
+                ghb_gbl: Ok(Default::default()),
+                ketamine: Ok(Default::default()),
+                lithium: Ok(Default::default()),
+                lsd: Ok(Default::default()),
+                maois: Ok(Default::default()),
+                mdma: Ok(Default::default()),
+                mephedrone: Ok(Default::default()),
+                mescaline: Ok(Default::default()),
+                mushrooms: Ok(Default::default()),
+                mxe: Ok(Default::default()),
+                nbomes: Ok(Default::default()),
+                nitrous: Ok(Default::default()),
+                opioids: Ok(Default::default()),
+                pcp: Ok(Default::default()),
+                ssris: Ok(Default::default()),
+                tramadol: Ok(Default::default()),
+            }
+        }
+    }
+    impl DrugCombos {
+        pub fn _2c_t_x<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self._2c_t_x = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for _2c_t_x: {}", e));
+            self
+        }
+        pub fn _2c_x<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self._2c_x = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for _2c_x: {}", e));
+            self
+        }
+        pub fn _5_meo_xxt<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self._5_meo_xxt = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for _5_meo_xxt: {}", e));
+            self
+        }
+        pub fn alcohol<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.alcohol = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for alcohol: {}", e));
+            self
+        }
+        pub fn amphetamines<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.amphetamines = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for amphetamines: {}", e));
+            self
+        }
+        pub fn amt<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.amt = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for amt: {}", e));
+            self
+        }
+        pub fn benzodiazepines<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.benzodiazepines = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for benzodiazepines: {}", e));
+            self
+        }
+        pub fn caffeine<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.caffeine = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for caffeine: {}", e));
+            self
+        }
+        pub fn cannabis<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.cannabis = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for cannabis: {}", e));
+            self
+        }
+        pub fn cocaine<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.cocaine = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for cocaine: {}", e));
+            self
+        }
+        pub fn dextromethorphan<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.dextromethorphan = value.try_into().map_err(|e| {
+                format!(
+                    "error converting supplied value for dextromethorphan: {}",
+                    e
+                )
+            });
+            self
+        }
+        pub fn diphenhydramine<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.diphenhydramine = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for diphenhydramine: {}", e));
+            self
+        }
+        pub fn dmt<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.dmt = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for dmt: {}", e));
+            self
+        }
+        pub fn dox<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.dox = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for dox: {}", e));
+            self
+        }
+        pub fn ghb_gbl<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.ghb_gbl = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for ghb_gbl: {}", e));
+            self
+        }
+        pub fn ketamine<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.ketamine = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for ketamine: {}", e));
+            self
+        }
+        pub fn lithium<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.lithium = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for lithium: {}", e));
+            self
+        }
+        pub fn lsd<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.lsd = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for lsd: {}", e));
+            self
+        }
+        pub fn maois<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.maois = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for maois: {}", e));
+            self
+        }
+        pub fn mdma<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.mdma = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for mdma: {}", e));
+            self
+        }
+        pub fn mephedrone<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.mephedrone = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for mephedrone: {}", e));
+            self
+        }
+        pub fn mescaline<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.mescaline = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for mescaline: {}", e));
+            self
+        }
+        pub fn mushrooms<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.mushrooms = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for mushrooms: {}", e));
+            self
+        }
+        pub fn mxe<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.mxe = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for mxe: {}", e));
+            self
+        }
+        pub fn nbomes<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.nbomes = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for nbomes: {}", e));
+            self
+        }
+        pub fn nitrous<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.nitrous = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for nitrous: {}", e));
+            self
+        }
+        pub fn opioids<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.opioids = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for opioids: {}", e));
+            self
+        }
+        pub fn pcp<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.pcp = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for pcp: {}", e));
+            self
+        }
+        pub fn ssris<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.ssris = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for ssris: {}", e));
+            self
+        }
+        pub fn tramadol<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Combo>>,
+            T::Error: std::fmt::Display,
+        {
+            self.tramadol = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for tramadol: {}", e));
+            self
+        }
+    }
+    impl std::convert::TryFrom<DrugCombos> for super::DrugCombos {
+        type Error = super::error::ConversionError;
+        fn try_from(value: DrugCombos) -> Result<Self, super::error::ConversionError> {
+            Ok(Self {
+                _2c_t_x: value._2c_t_x?,
+                _2c_x: value._2c_x?,
+                _5_meo_xxt: value._5_meo_xxt?,
+                alcohol: value.alcohol?,
+                amphetamines: value.amphetamines?,
+                amt: value.amt?,
+                benzodiazepines: value.benzodiazepines?,
+                caffeine: value.caffeine?,
+                cannabis: value.cannabis?,
+                cocaine: value.cocaine?,
+                dextromethorphan: value.dextromethorphan?,
+                diphenhydramine: value.diphenhydramine?,
+                dmt: value.dmt?,
+                dox: value.dox?,
+                ghb_gbl: value.ghb_gbl?,
+                ketamine: value.ketamine?,
+                lithium: value.lithium?,
+                lsd: value.lsd?,
+                maois: value.maois?,
+                mdma: value.mdma?,
+                mephedrone: value.mephedrone?,
+                mescaline: value.mescaline?,
+                mushrooms: value.mushrooms?,
+                mxe: value.mxe?,
+                nbomes: value.nbomes?,
+                nitrous: value.nitrous?,
+                opioids: value.opioids?,
+                pcp: value.pcp?,
+                ssris: value.ssris?,
+                tramadol: value.tramadol?,
+            })
+        }
+    }
+    impl From<super::DrugCombos> for DrugCombos {
+        fn from(value: super::DrugCombos) -> Self {
+            Self {
+                _2c_t_x: Ok(value._2c_t_x),
+                _2c_x: Ok(value._2c_x),
+                _5_meo_xxt: Ok(value._5_meo_xxt),
+                alcohol: Ok(value.alcohol),
+                amphetamines: Ok(value.amphetamines),
+                amt: Ok(value.amt),
+                benzodiazepines: Ok(value.benzodiazepines),
+                caffeine: Ok(value.caffeine),
+                cannabis: Ok(value.cannabis),
+                cocaine: Ok(value.cocaine),
+                dextromethorphan: Ok(value.dextromethorphan),
+                diphenhydramine: Ok(value.diphenhydramine),
+                dmt: Ok(value.dmt),
+                dox: Ok(value.dox),
+                ghb_gbl: Ok(value.ghb_gbl),
+                ketamine: Ok(value.ketamine),
+                lithium: Ok(value.lithium),
+                lsd: Ok(value.lsd),
+                maois: Ok(value.maois),
+                mdma: Ok(value.mdma),
+                mephedrone: Ok(value.mephedrone),
+                mescaline: Ok(value.mescaline),
+                mushrooms: Ok(value.mushrooms),
+                mxe: Ok(value.mxe),
+                nbomes: Ok(value.nbomes),
+                nitrous: Ok(value.nitrous),
+                opioids: Ok(value.opioids),
+                pcp: Ok(value.pcp),
+                ssris: Ok(value.ssris),
+                tramadol: Ok(value.tramadol),
+            }
+        }
+    }
+    #[derive(Clone, Debug)]
+    pub struct Duration {
+        buccal: Result<Option<String>, String>,
+        insufflated: Result<Option<String>, String>,
+        insufflated_ir: Result<Option<String>, String>,
+        insufflated_xr: Result<Option<String>, String>,
+        intramuscular: Result<Option<String>, String>,
+        intravenous: Result<Option<String>, String>,
+        metabolites: Result<Option<String>, String>,
+        oral: Result<Option<String>, String>,
+        oral_er: Result<Option<String>, String>,
+        oral_ir: Result<Option<String>, String>,
+        oral_maoi: Result<Option<String>, String>,
+        parent: Result<Option<String>, String>,
+        rectal: Result<Option<String>, String>,
+        smoked: Result<Option<String>, String>,
+        sublingual: Result<Option<String>, String>,
+        transdermal: Result<Option<String>, String>,
+        unit: Result<Option<super::Unit>, String>,
+        value: Result<Option<String>, String>,
+        vapourized: Result<Option<String>, String>,
+    }
+    impl Default for Duration {
+        fn default() -> Self {
+            Self {
+                buccal: Ok(Default::default()),
+                insufflated: Ok(Default::default()),
+                insufflated_ir: Ok(Default::default()),
+                insufflated_xr: Ok(Default::default()),
+                intramuscular: Ok(Default::default()),
+                intravenous: Ok(Default::default()),
+                metabolites: Ok(Default::default()),
+                oral: Ok(Default::default()),
+                oral_er: Ok(Default::default()),
+                oral_ir: Ok(Default::default()),
+                oral_maoi: Ok(Default::default()),
+                parent: Ok(Default::default()),
+                rectal: Ok(Default::default()),
+                smoked: Ok(Default::default()),
+                sublingual: Ok(Default::default()),
+                transdermal: Ok(Default::default()),
+                unit: Ok(Default::default()),
+                value: Ok(Default::default()),
+                vapourized: Ok(Default::default()),
+            }
+        }
+    }
+    impl Duration {
+        pub fn buccal<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.buccal = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for buccal: {}", e));
+            self
+        }
+        pub fn insufflated<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.insufflated = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for insufflated: {}", e));
+            self
+        }
+        pub fn insufflated_ir<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.insufflated_ir = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for insufflated_ir: {}", e));
+            self
+        }
+        pub fn insufflated_xr<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.insufflated_xr = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for insufflated_xr: {}", e));
+            self
+        }
+        pub fn intramuscular<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.intramuscular = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for intramuscular: {}", e));
+            self
+        }
+        pub fn intravenous<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.intravenous = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for intravenous: {}", e));
+            self
+        }
+        pub fn metabolites<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.metabolites = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for metabolites: {}", e));
+            self
+        }
+        pub fn oral<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.oral = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for oral: {}", e));
+            self
+        }
+        pub fn oral_er<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.oral_er = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for oral_er: {}", e));
+            self
+        }
+        pub fn oral_ir<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.oral_ir = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for oral_ir: {}", e));
+            self
+        }
+        pub fn oral_maoi<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.oral_maoi = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for oral_maoi: {}", e));
+            self
+        }
+        pub fn parent<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.parent = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for parent: {}", e));
+            self
+        }
+        pub fn rectal<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.rectal = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for rectal: {}", e));
+            self
+        }
+        pub fn smoked<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.smoked = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for smoked: {}", e));
+            self
+        }
+        pub fn sublingual<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.sublingual = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for sublingual: {}", e));
+            self
+        }
+        pub fn transdermal<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.transdermal = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for transdermal: {}", e));
+            self
+        }
+        pub fn unit<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<super::Unit>>,
+            T::Error: std::fmt::Display,
+        {
+            self.unit = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for unit: {}", e));
+            self
+        }
+        pub fn value<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.value = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for value: {}", e));
+            self
+        }
+        pub fn vapourized<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.vapourized = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for vapourized: {}", e));
+            self
+        }
+    }
+    impl std::convert::TryFrom<Duration> for super::Duration {
+        type Error = super::error::ConversionError;
+        fn try_from(value: Duration) -> Result<Self, super::error::ConversionError> {
+            Ok(Self {
+                buccal: value.buccal?,
+                insufflated: value.insufflated?,
+                insufflated_ir: value.insufflated_ir?,
+                insufflated_xr: value.insufflated_xr?,
+                intramuscular: value.intramuscular?,
+                intravenous: value.intravenous?,
+                metabolites: value.metabolites?,
+                oral: value.oral?,
+                oral_er: value.oral_er?,
+                oral_ir: value.oral_ir?,
+                oral_maoi: value.oral_maoi?,
+                parent: value.parent?,
+                rectal: value.rectal?,
+                smoked: value.smoked?,
+                sublingual: value.sublingual?,
+                transdermal: value.transdermal?,
+                unit: value.unit?,
+                value: value.value?,
+                vapourized: value.vapourized?,
+            })
+        }
+    }
+    impl From<super::Duration> for Duration {
+        fn from(value: super::Duration) -> Self {
+            Self {
+                buccal: Ok(value.buccal),
+                insufflated: Ok(value.insufflated),
+                insufflated_ir: Ok(value.insufflated_ir),
+                insufflated_xr: Ok(value.insufflated_xr),
+                intramuscular: Ok(value.intramuscular),
+                intravenous: Ok(value.intravenous),
+                metabolites: Ok(value.metabolites),
+                oral: Ok(value.oral),
+                oral_er: Ok(value.oral_er),
+                oral_ir: Ok(value.oral_ir),
+                oral_maoi: Ok(value.oral_maoi),
+                parent: Ok(value.parent),
+                rectal: Ok(value.rectal),
+                smoked: Ok(value.smoked),
+                sublingual: Ok(value.sublingual),
+                transdermal: Ok(value.transdermal),
+                unit: Ok(value.unit),
+                value: Ok(value.value),
+                vapourized: Ok(value.vapourized),
+            }
+        }
+    }
+    #[derive(Clone, Debug)]
+    pub struct Links {
+        experiences: Result<String, String>,
+        pihkal: Result<Option<String>, String>,
+        tihkal: Result<Option<String>, String>,
+    }
+    impl Default for Links {
+        fn default() -> Self {
+            Self {
+                experiences: Err("no value supplied for experiences".to_string()),
+                pihkal: Ok(Default::default()),
+                tihkal: Ok(Default::default()),
+            }
+        }
+    }
+    impl Links {
+        pub fn experiences<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<String>,
+            T::Error: std::fmt::Display,
+        {
+            self.experiences = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for experiences: {}", e));
+            self
+        }
+        pub fn pihkal<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.pihkal = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for pihkal: {}", e));
+            self
+        }
+        pub fn tihkal<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.tihkal = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for tihkal: {}", e));
+            self
+        }
+    }
+    impl std::convert::TryFrom<Links> for super::Links {
+        type Error = super::error::ConversionError;
+        fn try_from(value: Links) -> Result<Self, super::error::ConversionError> {
+            Ok(Self {
+                experiences: value.experiences?,
+                pihkal: value.pihkal?,
+                tihkal: value.tihkal?,
+            })
+        }
+    }
+    impl From<super::Links> for Links {
+        fn from(value: super::Links) -> Self {
+            Self {
+                experiences: Ok(value.experiences),
+                pihkal: Ok(value.pihkal),
+                tihkal: Ok(value.tihkal),
+            }
+        }
+    }
+    #[derive(Clone, Debug)]
+    pub struct Properties {
+        adverse_effects: Result<Option<String>, String>,
+        after_effects: Result<Option<String>, String>,
+        aliases: Result<Vec<String>, String>,
+        avoid: Result<Option<String>, String>,
+        bioavailability: Result<Option<String>, String>,
+        calculator: Result<Option<String>, String>,
+        categories: Result<Vec<super::Category>, String>,
+        chart: Result<Option<String>, String>,
+        chemistry: Result<Option<String>, String>,
+        comeup: Result<Option<String>, String>,
+        contraindications: Result<Option<String>, String>,
+        detection: Result<Option<String>, String>,
+        dose: Result<Option<String>, String>,
+        dose_to_diazepam: Result<Option<String>, String>,
+        duration: Result<Option<String>, String>,
+        effects: Result<Option<String>, String>,
+        experiences: Result<Option<String>, String>,
+        general_advice: Result<Option<String>, String>,
+        half_life: Result<Option<String>, String>,
+        legal: Result<Option<String>, String>,
+        marquis: Result<Option<String>, String>,
+        mdma: Result<Option<String>, String>,
+        molecule: Result<Option<String>, String>,
+        note: Result<Option<String>, String>,
+        obtain: Result<Option<String>, String>,
+        onset: Result<Option<String>, String>,
+        oral: Result<Option<String>, String>,
+        overdose_symptoms: Result<Option<String>, String>,
+        pharmacodynamics: Result<Option<String>, String>,
+        pharmacokinetics: Result<Option<String>, String>,
+        pharmacology: Result<Option<String>, String>,
+        potentiators: Result<Option<String>, String>,
+        risks: Result<Option<String>, String>,
+        side_effects: Result<Option<String>, String>,
+        summary: Result<Option<String>, String>,
+        test_kits: Result<Option<String>, String>,
+        tolerance: Result<Option<String>, String>,
+        vaporization: Result<Option<String>, String>,
+        warning: Result<Option<String>, String>,
+        wiki: Result<Option<String>, String>,
+    }
+    impl Default for Properties {
+        fn default() -> Self {
+            Self {
+                adverse_effects: Ok(Default::default()),
+                after_effects: Ok(Default::default()),
+                aliases: Ok(Default::default()),
+                avoid: Ok(Default::default()),
+                bioavailability: Ok(Default::default()),
+                calculator: Ok(Default::default()),
+                categories: Ok(Default::default()),
+                chart: Ok(Default::default()),
+                chemistry: Ok(Default::default()),
+                comeup: Ok(Default::default()),
+                contraindications: Ok(Default::default()),
+                detection: Ok(Default::default()),
+                dose: Ok(Default::default()),
+                dose_to_diazepam: Ok(Default::default()),
+                duration: Ok(Default::default()),
+                effects: Ok(Default::default()),
+                experiences: Ok(Default::default()),
+                general_advice: Ok(Default::default()),
+                half_life: Ok(Default::default()),
+                legal: Ok(Default::default()),
+                marquis: Ok(Default::default()),
+                mdma: Ok(Default::default()),
+                molecule: Ok(Default::default()),
+                note: Ok(Default::default()),
+                obtain: Ok(Default::default()),
+                onset: Ok(Default::default()),
+                oral: Ok(Default::default()),
+                overdose_symptoms: Ok(Default::default()),
+                pharmacodynamics: Ok(Default::default()),
+                pharmacokinetics: Ok(Default::default()),
+                pharmacology: Ok(Default::default()),
+                potentiators: Ok(Default::default()),
+                risks: Ok(Default::default()),
+                side_effects: Ok(Default::default()),
+                summary: Ok(Default::default()),
+                test_kits: Ok(Default::default()),
+                tolerance: Ok(Default::default()),
+                vaporization: Ok(Default::default()),
+                warning: Ok(Default::default()),
+                wiki: Ok(Default::default()),
+            }
+        }
+    }
+    impl Properties {
+        pub fn adverse_effects<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.adverse_effects = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for adverse_effects: {}", e));
+            self
+        }
+        pub fn after_effects<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.after_effects = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for after_effects: {}", e));
+            self
+        }
+        pub fn aliases<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Vec<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.aliases = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for aliases: {}", e));
+            self
+        }
+        pub fn avoid<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.avoid = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for avoid: {}", e));
+            self
+        }
+        pub fn bioavailability<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.bioavailability = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for bioavailability: {}", e));
+            self
+        }
+        pub fn calculator<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.calculator = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for calculator: {}", e));
+            self
+        }
+        pub fn categories<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Vec<super::Category>>,
+            T::Error: std::fmt::Display,
+        {
+            self.categories = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for categories: {}", e));
+            self
+        }
+        pub fn chart<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.chart = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for chart: {}", e));
+            self
+        }
+        pub fn chemistry<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.chemistry = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for chemistry: {}", e));
+            self
+        }
+        pub fn comeup<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.comeup = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for comeup: {}", e));
+            self
+        }
+        pub fn contraindications<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.contraindications = value.try_into().map_err(|e| {
+                format!(
+                    "error converting supplied value for contraindications: {}",
+                    e
+                )
+            });
+            self
+        }
+        pub fn detection<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.detection = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for detection: {}", e));
+            self
+        }
+        pub fn dose<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.dose = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for dose: {}", e));
+            self
+        }
+        pub fn dose_to_diazepam<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.dose_to_diazepam = value.try_into().map_err(|e| {
+                format!(
+                    "error converting supplied value for dose_to_diazepam: {}",
+                    e
+                )
+            });
+            self
+        }
+        pub fn duration<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.duration = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for duration: {}", e));
+            self
+        }
+        pub fn effects<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.effects = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for effects: {}", e));
+            self
+        }
+        pub fn experiences<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.experiences = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for experiences: {}", e));
+            self
+        }
+        pub fn general_advice<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.general_advice = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for general_advice: {}", e));
+            self
+        }
+        pub fn half_life<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.half_life = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for half_life: {}", e));
+            self
+        }
+        pub fn legal<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.legal = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for legal: {}", e));
+            self
+        }
+        pub fn marquis<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.marquis = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for marquis: {}", e));
+            self
+        }
+        pub fn mdma<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.mdma = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for mdma: {}", e));
+            self
+        }
+        pub fn molecule<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.molecule = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for molecule: {}", e));
+            self
+        }
+        pub fn note<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.note = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for note: {}", e));
+            self
+        }
+        pub fn obtain<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.obtain = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for obtain: {}", e));
+            self
+        }
+        pub fn onset<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.onset = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for onset: {}", e));
+            self
+        }
+        pub fn oral<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.oral = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for oral: {}", e));
+            self
+        }
+        pub fn overdose_symptoms<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.overdose_symptoms = value.try_into().map_err(|e| {
+                format!(
+                    "error converting supplied value for overdose_symptoms: {}",
+                    e
+                )
+            });
+            self
+        }
+        pub fn pharmacodynamics<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.pharmacodynamics = value.try_into().map_err(|e| {
+                format!(
+                    "error converting supplied value for pharmacodynamics: {}",
+                    e
+                )
+            });
+            self
+        }
+        pub fn pharmacokinetics<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.pharmacokinetics = value.try_into().map_err(|e| {
+                format!(
+                    "error converting supplied value for pharmacokinetics: {}",
+                    e
+                )
+            });
+            self
+        }
+        pub fn pharmacology<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.pharmacology = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for pharmacology: {}", e));
+            self
+        }
+        pub fn potentiators<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.potentiators = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for potentiators: {}", e));
+            self
+        }
+        pub fn risks<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.risks = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for risks: {}", e));
+            self
+        }
+        pub fn side_effects<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.side_effects = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for side_effects: {}", e));
+            self
+        }
+        pub fn summary<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.summary = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for summary: {}", e));
+            self
+        }
+        pub fn test_kits<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.test_kits = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for test_kits: {}", e));
+            self
+        }
+        pub fn tolerance<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.tolerance = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for tolerance: {}", e));
+            self
+        }
+        pub fn vaporization<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.vaporization = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for vaporization: {}", e));
+            self
+        }
+        pub fn warning<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.warning = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for warning: {}", e));
+            self
+        }
+        pub fn wiki<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.wiki = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for wiki: {}", e));
+            self
+        }
+    }
+    impl std::convert::TryFrom<Properties> for super::Properties {
+        type Error = super::error::ConversionError;
+        fn try_from(value: Properties) -> Result<Self, super::error::ConversionError> {
+            Ok(Self {
+                adverse_effects: value.adverse_effects?,
+                after_effects: value.after_effects?,
+                aliases: value.aliases?,
+                avoid: value.avoid?,
+                bioavailability: value.bioavailability?,
+                calculator: value.calculator?,
+                categories: value.categories?,
+                chart: value.chart?,
+                chemistry: value.chemistry?,
+                comeup: value.comeup?,
+                contraindications: value.contraindications?,
+                detection: value.detection?,
+                dose: value.dose?,
+                dose_to_diazepam: value.dose_to_diazepam?,
+                duration: value.duration?,
+                effects: value.effects?,
+                experiences: value.experiences?,
+                general_advice: value.general_advice?,
+                half_life: value.half_life?,
+                legal: value.legal?,
+                marquis: value.marquis?,
+                mdma: value.mdma?,
+                molecule: value.molecule?,
+                note: value.note?,
+                obtain: value.obtain?,
+                onset: value.onset?,
+                oral: value.oral?,
+                overdose_symptoms: value.overdose_symptoms?,
+                pharmacodynamics: value.pharmacodynamics?,
+                pharmacokinetics: value.pharmacokinetics?,
+                pharmacology: value.pharmacology?,
+                potentiators: value.potentiators?,
+                risks: value.risks?,
+                side_effects: value.side_effects?,
+                summary: value.summary?,
+                test_kits: value.test_kits?,
+                tolerance: value.tolerance?,
+                vaporization: value.vaporization?,
+                warning: value.warning?,
+                wiki: value.wiki?,
+            })
+        }
+    }
+    impl From<super::Properties> for Properties {
+        fn from(value: super::Properties) -> Self {
+            Self {
+                adverse_effects: Ok(value.adverse_effects),
+                after_effects: Ok(value.after_effects),
+                aliases: Ok(value.aliases),
+                avoid: Ok(value.avoid),
+                bioavailability: Ok(value.bioavailability),
+                calculator: Ok(value.calculator),
+                categories: Ok(value.categories),
+                chart: Ok(value.chart),
+                chemistry: Ok(value.chemistry),
+                comeup: Ok(value.comeup),
+                contraindications: Ok(value.contraindications),
+                detection: Ok(value.detection),
+                dose: Ok(value.dose),
+                dose_to_diazepam: Ok(value.dose_to_diazepam),
+                duration: Ok(value.duration),
+                effects: Ok(value.effects),
+                experiences: Ok(value.experiences),
+                general_advice: Ok(value.general_advice),
+                half_life: Ok(value.half_life),
+                legal: Ok(value.legal),
+                marquis: Ok(value.marquis),
+                mdma: Ok(value.mdma),
+                molecule: Ok(value.molecule),
+                note: Ok(value.note),
+                obtain: Ok(value.obtain),
+                onset: Ok(value.onset),
+                oral: Ok(value.oral),
+                overdose_symptoms: Ok(value.overdose_symptoms),
+                pharmacodynamics: Ok(value.pharmacodynamics),
+                pharmacokinetics: Ok(value.pharmacokinetics),
+                pharmacology: Ok(value.pharmacology),
+                potentiators: Ok(value.potentiators),
+                risks: Ok(value.risks),
+                side_effects: Ok(value.side_effects),
+                summary: Ok(value.summary),
+                test_kits: Ok(value.test_kits),
+                tolerance: Ok(value.tolerance),
+                vaporization: Ok(value.vaporization),
+                warning: Ok(value.warning),
+                wiki: Ok(value.wiki),
+            }
+        }
+    }
+    #[derive(Clone, Debug)]
+    pub struct SourceData {
+        author: Result<Option<String>, String>,
+        title: Result<Option<String>, String>,
+        url: Result<Option<String>, String>,
+    }
+    impl Default for SourceData {
+        fn default() -> Self {
+            Self {
+                author: Ok(Default::default()),
+                title: Ok(Default::default()),
+                url: Ok(Default::default()),
+            }
+        }
+    }
+    impl SourceData {
+        pub fn author<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.author = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for author: {}", e));
+            self
+        }
+        pub fn title<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.title = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for title: {}", e));
+            self
+        }
+        pub fn url<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Option<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.url = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for url: {}", e));
+            self
+        }
+    }
+    impl std::convert::TryFrom<SourceData> for super::SourceData {
+        type Error = super::error::ConversionError;
+        fn try_from(value: SourceData) -> Result<Self, super::error::ConversionError> {
+            Ok(Self {
+                author: value.author?,
+                title: value.title?,
+                url: value.url?,
+            })
+        }
+    }
+    impl From<super::SourceData> for SourceData {
+        fn from(value: super::SourceData) -> Self {
+            Self {
+                author: Ok(value.author),
+                title: Ok(value.title),
+                url: Ok(value.url),
+            }
+        }
+    }
+    #[derive(Clone, Debug)]
+    pub struct Sources {
+        bioavailability: Result<Vec<String>, String>,
+        dose: Result<Vec<String>, String>,
+        duration: Result<Vec<String>, String>,
+        general: Result<Vec<String>, String>,
+        legality: Result<Vec<String>, String>,
+        onset: Result<Vec<String>, String>,
+    }
+    impl Default for Sources {
+        fn default() -> Self {
+            Self {
+                bioavailability: Ok(Default::default()),
+                dose: Ok(Default::default()),
+                duration: Ok(Default::default()),
+                general: Ok(Default::default()),
+                legality: Ok(Default::default()),
+                onset: Ok(Default::default()),
+            }
+        }
+    }
+    impl Sources {
+        pub fn bioavailability<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Vec<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.bioavailability = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for bioavailability: {}", e));
+            self
+        }
+        pub fn dose<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Vec<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.dose = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for dose: {}", e));
+            self
+        }
+        pub fn duration<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Vec<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.duration = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for duration: {}", e));
+            self
+        }
+        pub fn general<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Vec<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.general = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for general: {}", e));
+            self
+        }
+        pub fn legality<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Vec<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.legality = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for legality: {}", e));
+            self
+        }
+        pub fn onset<T>(mut self, value: T) -> Self
+        where
+            T: std::convert::TryInto<Vec<String>>,
+            T::Error: std::fmt::Display,
+        {
+            self.onset = value
+                .try_into()
+                .map_err(|e| format!("error converting supplied value for onset: {}", e));
+            self
+        }
+    }
+    impl std::convert::TryFrom<Sources> for super::Sources {
+        type Error = super::error::ConversionError;
+        fn try_from(value: Sources) -> Result<Self, super::error::ConversionError> {
+            Ok(Self {
+                bioavailability: value.bioavailability?,
+                dose: value.dose?,
+                duration: value.duration?,
+                general: value.general?,
+                legality: value.legality?,
+                onset: value.onset?,
+            })
+        }
+    }
+    impl From<super::Sources> for Sources {
+        fn from(value: super::Sources) -> Self {
+            Self {
+                bioavailability: Ok(value.bioavailability),
+                dose: Ok(value.dose),
+                duration: Ok(value.duration),
+                general: Ok(value.general),
+                legality: Ok(value.legality),
+                onset: Ok(value.onset),
+            }
+        }
+    }
+}
diff --git a/client/src/drugs/mod.rs b/client/src/drugs/mod.rs
new file mode 100644
index 0000000..42027dc
--- /dev/null
+++ b/client/src/drugs/mod.rs
@@ -0,0 +1 @@
+mod drug_schema;
diff --git a/client/src/main.rs b/client/src/main.rs
index 574adc0..a358080 100644
--- a/client/src/main.rs
+++ b/client/src/main.rs
@@ -17,12 +17,12 @@ mod util;
 
 mod drugs_parser;
 
-mod substances_new;
+mod drugs;
 
-mod ingestions;
-mod ingestions_util;
-mod substance_util;
-mod substances;
+// mod ingestions;
+// mod ingestions_util;
+// mod substance_util;
+// mod substances;
 
 // mod drug_parser;
 
@@ -77,19 +77,19 @@ fn print_completions<G: Generator>(gen: G, cmd: &mut Command) {
 
 fn main() {
     drugs_parser::parse();
-    ensure_files();
+    // ensure_files();
 
     let cli = Cli::parse();
 
     match cli.command {
-        Some(Commands::AddIngestion) => ingestions::add_ingestion(),
-        Some(Commands::EditIngestion) => ingestions::edit_ingestion().unwrap(),
-        Some(Commands::ListIngestions) => ingestions::list_ingestions().unwrap(),
-        Some(Commands::RemoveIngestion) => {}
-        Some(Commands::AddSubstance) => substances::add_substance().unwrap(),
-        Some(Commands::EditSubstance) => substances::edit_substance().unwrap(),
-        Some(Commands::ListSubstances) => substances::list_substances().unwrap(),
-        Some(Commands::RemoveSubstance) => substances::remove_substance().unwrap(),
+        // Some(Commands::AddIngestion) => ingestions::add_ingestion(),
+        // Some(Commands::EditIngestion) => ingestions::edit_ingestion().unwrap(),
+        // Some(Commands::ListIngestions) => ingestions::list_ingestions().unwrap(),
+        // Some(Commands::RemoveIngestion) => {}
+        // Some(Commands::AddSubstance) => substances::add_substance().unwrap(),
+        // Some(Commands::EditSubstance) => substances::edit_substance().unwrap(),
+        // Some(Commands::ListSubstances) => substances::list_substances().unwrap(),
+        // Some(Commands::RemoveSubstance) => substances::remove_substance().unwrap(),
         Some(Commands::GenerateCompletions { shell }) => {
             let mut cmd = Cli::command();
             eprintln!("Generating completion file for {shell}...");
@@ -103,45 +103,46 @@ fn main() {
         }
 
         None => {}
+        _ => {}
     }
 }
 
-fn ensure_files() {
-    if !util::path_exists(LOCAL_PATH.to_string()) {
-        match std::fs::create_dir(LOCAL_PATH.to_string()) {
-            Ok(_) => {}
-            Err(e) => {
-                eprintln!("Could not create data directory with error: {:?}", e);
-                std::process::exit(1);
-            }
-        }
-    }
-    if !util::path_exists(SUBSTANCES_FILE.to_string()) {
-        match substance_util::create_substances_file() {
-            Ok(_) => {
-                println!(
-                    "Created substances file at {:?}",
-                    SUBSTANCES_FILE.to_string()
-                )
-            }
-            Err(_) => {
-                eprintln!("Could not create substances file");
-                panic!()
-            }
-        };
-    }
-    if !util::path_exists(INGESTIONS_FILE.to_string()) {
-        match ingestions::create_ingestions_file() {
-            Ok(_) => {
-                println!(
-                    "Created ingestions file at {:?}",
-                    INGESTIONS_FILE.to_string()
-                )
-            }
-            Err(_) => {
-                eprintln!("Could not create substances file");
-                panic!()
-            }
-        };
-    }
-}
+// fn ensure_files() {
+//     if !util::path_exists(LOCAL_PATH.to_string()) {
+//         match std::fs::create_dir(LOCAL_PATH.to_string()) {
+//             Ok(_) => {}
+//             Err(e) => {
+//                 eprintln!("Could not create data directory with error: {:?}", e);
+//                 std::process::exit(1);
+//             }
+//         }
+//     }
+//     if !util::path_exists(SUBSTANCES_FILE.to_string()) {
+//         match substance_util::create_substances_file() {
+//             Ok(_) => {
+//                 println!(
+//                     "Created substances file at {:?}",
+//                     SUBSTANCES_FILE.to_string()
+//                 )
+//             }
+//             Err(_) => {
+//                 eprintln!("Could not create substances file");
+//                 panic!()
+//             }
+//         };
+//     }
+//     if !util::path_exists(INGESTIONS_FILE.to_string()) {
+//         match ingestions::create_ingestions_file() {
+//             Ok(_) => {
+//                 println!(
+//                     "Created ingestions file at {:?}",
+//                     INGESTIONS_FILE.to_string()
+//                 )
+//             }
+//             Err(_) => {
+//                 eprintln!("Could not create substances file");
+//                 panic!()
+//             }
+//         };
+//     }
+// }
diff --git a/client/src/substances_new/mod.rs b/client/src/substances_new/mod.rs
deleted file mode 100644
index cf371fc..0000000
--- a/client/src/substances_new/mod.rs
+++ /dev/null
@@ -1,356 +0,0 @@
-// export type Drug = {
-//   aliases?: string[];
-//   categories?: Category[];
-//   formatted_aftereffects?: Duration;
-//   formatted_dose?: Dose;
-//   formatted_duration?: Duration;
-//   formatted_effects?: string[];
-//   formatted_onset?: Duration;
-//   links?: Links;
-//   name: string;
-//   pretty_name: string;
-//   properties: Properties;
-//   pweffects?: { [key: string]: string };
-//   dose_note?: string;
-//   sources?: Sources;
-//   combos?: Interactions;
-// };
-//
-// export enum Category {
-//   Barbiturate = "barbiturate",
-//   Benzodiazepine = "benzodiazepine",
-//   Common = "common",
-//   Deliriant = "deliriant",
-//   Depressant = "depressant",
-//   Dissociative = "dissociative",
-//   Empathogen = "empathogen",
-//   HabitForming = "habit-forming",
-//   Inactive = "inactive",
-//   Nootropic = "nootropic",
-//   Opioid = "opioid",
-//   Psychedelic = "psychedelic",
-//   ResearchChemical = "research-chemical",
-//   Ssri = "ssri",
-//   Stimulant = "stimulant",
-//   Supplement = "supplement",
-//   Tentative = "tentative",
-// }
-//
-// export type Duration = {
-//   _unit: Unit;
-//   value?: string;
-//   insufflated?: string;
-//   oral?: string;
-//   rectal?: string;
-//   vapourized?: string;
-//   smoked?: string;
-//   Oral_ER?: string;
-//   Oral_IR?: string;
-//   Oral_MAOI?: string;
-//   intramuscular?: string;
-//   intravenous?: string;
-//   metabolites?: string;
-//   parent?: string;
-//   oralMAOI?: string;
-//   buccal?: string;
-//   transdermal?: string;
-//   sublingual?: string;
-//   Insufflated_IR?: string;
-//   Insufflated_XR?: string;
-// };
-//
-// export type Dose = {
-//   oral?: Dosage;
-//   insufflated?: Dosage;
-//   rectal?: Dosage;
-//   vapourized?: Dosage;
-//   intravenous?: Dosage;
-//   smoked?: Dosage;
-//   sublingual?: Dosage;
-//   buccal?: Dosage;
-//   intramuscular?: Dosage;
-//   transdermal?: Dosage;
-//   hbwr?: Dosage;
-//   Morning_Glory?: Dosage;
-//   dried?: Dosage;
-//   fresh?: Dosage;
-//   "Insufflated(Pure)"?: Dosage;
-//   "Oral(Benzedrex)"?: Dosage;
-//   "Oral(Pure)"?: Dosage;
-//   dry?: Dosage;
-//   wet?: Dosage;
-// };
-//
-// export type Dosage = {
-//   common?: string;
-//   light?: string;
-//   strong?: string;
-//   threshold?: string;
-//   heavy?: string;
-//   dangerous?: string;
-//   fatal?: string;
-//   note?: string;
-// };
-//
-// export type Links = {
-//   experiences: string;
-//   pihkal?: string;
-//   tihkal?: string;
-// };
-//
-// export type Properties = {
-//   "after-effects"?: string;
-//   aliases?: string[];
-//   avoid?: string;
-//   categories?: Category[];
-//   dose?: string;
-//   duration?: string;
-//   "half-life"?: string;
-//   onset?: string;
-//   summary?: string;
-//   "test-kits"?: string;
-//   experiences?: string;
-//   warning?: string;
-//   marquis?: string;
-//   effects?: string;
-//   risks?: string;
-//   comeup?: string;
-//   note?: string;
-//   detection?: string;
-//   wiki?: string;
-//   mdma?: string;
-//   tolerance?: string;
-//   bioavailability?: string;
-//   dose_to_diazepam?: string;
-//   "adverse-effects"?: string;
-//   chemistry?: string;
-//   contraindications?: string;
-//   legal?: string;
-//   "overdose-symptoms"?: string;
-//   pharmacokinetics?: string;
-//   pharmacology?: string;
-//   obtain?: string;
-//   pharmacodynamics?: string;
-//   "side-effects"?: string;
-//   molecule?: string;
-//   vaporization?: string;
-//   calculator?: string;
-//   chart?: string;
-//   oral?: string;
-//   "general-advice"?: string;
-//   potentiators?: string;
-// };
-//
-// export interface Combos {
-//   "2c-t-x":         Interactions;
-//   "2c-x":           Interactions;
-//   "5-meo-xxt":      Interactions;
-//   alcohol:          Interactions;
-//   amphetamines:     Interactions;
-//   amt:              Interactions;
-//   benzodiazepines:  Interactions;
-//   caffeine:         Interactions;
-//   cannabis:         Interactions;
-//   cocaine:          Interactions;
-//   diphenhydramine:  Interactions;
-//   dextromethorphan: Interactions;
-//   dmt:              Interactions;
-//   dox:              Interactions;
-//   "ghb/gbl":        Interactions;
-//   ketamine:         Interactions;
-//   lithium:          Interactions;
-//   lsd:              Interactions;
-//   maois:            Interactions;
-//   mdma:             Interactions;
-//   mephedrone:       Interactions;
-//   mescaline:        Interactions;
-//   mushrooms:        Interactions;
-//   mxe:              Interactions;
-//   nbomes:           Interactions;
-//   nitrous:          Interactions;
-//   opioids:          Interactions;
-//   pcp:              Interactions;
-//   ssris:            Interactions;
-//   tramadol:         Interactions;
-// }
-//
-// export interface Interactions {
-//   "2c-t-x"?:         ComboData;
-//   "2c-x"?:           ComboData;
-//   "5-meo-xxt"?:      ComboData;
-//   alcohol?:          ComboData;
-//   amphetamines?:     ComboData;
-//   amt?:              ComboData;
-//   benzodiazepines?:  ComboData;
-//   caffeine?:         ComboData;
-//   cannabis?:         ComboData;
-//   cocaine?:          ComboData;
-//   diphenhydramine?:  ComboData;
-//   dextromethorphan?: ComboData;
-//   dmt?:              ComboData;
-//   dox?:              ComboData;
-//   "ghb/gbl"?:        ComboData;
-//   lithium?:          ComboData;
-//   ketamine?:         ComboData;
-//   lsd?:              ComboData;
-//   maois?:            ComboData;
-//   mdma?:             ComboData;
-//   mephedrone?:       ComboData;
-//   mescaline?:        ComboData;
-//   mushrooms?:        ComboData;
-//   mxe?:              ComboData;
-//   nbomes?:           ComboData;
-//   nitrous?:          ComboData;
-//   opioids?:          ComboData;
-//   pcp?:              ComboData;
-//   ssris?:            ComboData;
-//   tramadol?:         ComboData;
-// }
-//
-// export interface ComboData {
-//   note?: string;
-//   sources?: {
-//     author: string;
-//     title: string;
-//     url: string;
-//   }[];
-//   status: Status;
-// }
-//
-// export enum Status {
-//   Caution = "Caution",
-//   Dangerous = "Dangerous",
-//   LowRiskDecrease = "Low Risk & Decrease",
-//   LowRiskNoSynergy = "Low Risk & No Synergy",
-//   LowRiskSynergy = "Low Risk & Synergy",
-//   Self = "Self",
-//   Unsafe = "Unsafe",
-// }
-//
-// export type ComboDefinitions = {
-//   status:     Status;
-//   emoji:      string;
-//   color:      string;
-//   definition: string;
-//   thumbnail:  string;
-// }
-//
-// export enum Unit {
-//   Hours = "hours",
-//   Minutes = "minutes",
-// }
-//
-// export type Sources = {
-//   general?: string[];
-//   dose?: string[];
-//   duration?: string[];
-//   bioavailability?: string[];
-//   legality?: string[];
-//   onset?: string[];
-// };
-
-pub struct Dug {
-    aliases: Option<Vec<String>>,
-    categories: Option<Vec<Category>>,
-    formatted_aftereffects: Option<Duration>,
-    formatted_dose: Option<Dose>,
-    formatted_duration: Option<Duration>,
-    formatted_effects: Option<Vec<String>>,
-    formatted_onset: Option<Duration>,
-    links: Option<Links>,
-    name: String,
-    pretty_name: String,
-    properties: Properties,
-    pweffects: Option<(String, Strin)>,
-    dose_note: Option<String>,
-    sources: Option<Sources>,
-    combos: Option<Interactions>,
-}
-
-pub enum Category {
-    Barbiturate,
-    Benzodiazepine,
-    Common,
-    Deliriant,
-    Depressant,
-    Dissociative,
-    Empathogen,
-    HabitForming,
-    Inactive,
-    Nootropic,
-    Opioid,
-    Psychedelic,
-    ResearchChemical,
-    Ssri,
-    Stimulant,
-    Supplement,
-    Tentative,
-}
-
-pub struct Duration {
-    unit: Unit,
-    value: Option<String>,
-    insufflated: Option<String>,
-    oral: Option<String>,
-    rectal: Option<String>,
-    vapourized: Option<String>,
-    smoked: Option<String>,
-    oral_ER: Option<String>,
-    oral_IR: Option<String>,
-    oral_MAOI: Option<String>,
-    intramuscular: Option<String>,
-    intravenous: Option<String>,
-    metabolites: Option<String>,
-    parent: Option<String>,
-    oralMAOI: Option<String>,
-    buccal: Option<String>,
-    transdermal: Option<String>,
-    sublingual: Option<String>,
-    Insufflated_IR: Option<String>,
-    Insufflated_XR: Option<String>,
-}
-
-pub struct Dose {
-    oral: Option<Dosage>,
-    insufflated: Option<Dosage>,
-    rectal: Option<Dosage>,
-    vapourized: Option<Dosage>,
-    intravenous: Option<Dosage>,
-    smoked: Option<Dosage>,
-    sublingual: Option<Dosage>,
-    buccal: Option<Dosage>,
-    intramuscular: Option<Dosage>,
-    transdermal: Option<Dosage>,
-    hbwr: Option<Dosage>,
-    morning_glory: Option<Dosage>,
-    dried: Option<Dosage>,
-    fresh: Option<Dosage>,
-    insufflated_pure: Option<Dosage>,
-    oral_benzedrex: Option<Dosage>,
-    oral_pure: Option<Dosage>,
-    dry: Option<Dosage>,
-    wet: Option<Dosage>,
-}
-
-pub struct Dosage {
-    common: Option<String>,
-    light: Option<String>,
-    strong: Option<String>,
-    threshold: Option<String>,
-    heavy: Option<String>,
-    dangerous: Option<String>,
-    fatal: Option<String>,
-    note: Option<String>,
-}
-
-pub struct Links {
-    experiences: String,
-    pihkal: Option<String>,
-    tihkal: Option<String>,
-}
-
-pub struct Properties {
-    after_effects: Option<String>,
-    aliases: Option<Vec<String>>,
-    avoid: Option<String>,
-}
diff --git a/server/src/main.rs b/server/src/main.rs
index 7bf897d..3296c36 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -1,6 +1,6 @@
 use tonic;
 
 fn main() {
-    let addr = "[::1]:50051".parse();
+    // let addr = "[::1]:50051".parse();
     println!("Hello, world!");
 }