diff options
Diffstat (limited to 'development/libs/barrel/src/types/impls.rs')
-rw-r--r-- | development/libs/barrel/src/types/impls.rs | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/development/libs/barrel/src/types/impls.rs b/development/libs/barrel/src/types/impls.rs new file mode 100644 index 000000000000..cfbb56b5ce9f --- /dev/null +++ b/development/libs/barrel/src/types/impls.rs @@ -0,0 +1,165 @@ +//! Implementation specifics for the type system + +use super::WrappedDefault; + +/// A smol wrapper around `Vec<T>` to get around the orphan rules +#[derive(PartialEq, Debug, Clone)] +pub struct WrapVec<T>(pub Vec<T>); + +/// Core type enum, describing the basic type +#[derive(PartialEq, Debug, Clone)] +pub enum BaseType { + /// Strings + Text, + /// Like a String but worse + Varchar(usize), + /// Primary key (utility for incrementing integer – postgres supports this, we just mirror it) + Primary, + /// Simple integer + Integer, + /// Floating point number + Float, + /// Like Float but `~ ~ d o u b l e p r e c i s i o n ~ ~` + Double, + /// A unique identifier type + UUID, + /// True or False + Boolean, + /// Json encoded data + Json, + /// Date And Time + Date, + /// <inconceivable jibberish> + Binary, + /// Foreign key to other table + Foreign(Option<String>, String, WrapVec<String>), + /// I have no idea what you are – but I *like* it + Custom(&'static str), + /// Any of the above, but **many** of them + Array(Box<BaseType>), + /// Indexing over multiple columns + Index(Vec<String>), +} + +/// A database column type and all the metadata attached to it +/// +/// Using this struct directly is not recommended. Instead, you should be +/// using the constructor APIs in the `types` module. +/// +/// A `Type` is an enum provided to other `barrel` APIs in order +/// to generate SQL datatypes. Working with them directly is possible +/// but not recommended. +/// +/// Instead, you can use these helper functions to construct `Type` enums of +/// different...types and constraints. Field metadata is added via chainable +/// factory pattern functions. +/// +/// ## Default values +/// +/// If no additional arguments are provided, some assumptions will be made +/// about the metadata of a column type. +/// +/// - `nullable`: `false` +/// - `indexed`: `false` +/// - `unique`: `false` +/// - `default`: `None` +/// - `size`: `None` (which will error if size is important) +/// +/// ## Examples +/// +/// ```rust,norun +/// extern crate barrel; +/// use barrel::types::*; +/// +/// // Make your own Primary key :) +/// let col = integer().increments(true).unique(true); +/// ``` +#[derive(Debug, Clone, PartialEq)] +pub struct Type { + pub nullable: bool, + pub unique: bool, + pub increments: bool, + pub indexed: bool, + pub primary: bool, + pub default: Option<WrappedDefault<'static>>, + pub size: Option<usize>, + pub inner: BaseType, +} + +/// This is a public API, be considered about breaking thigns +#[cfg_attr(rustfmt, rustfmt_skip)] +impl Type { + pub(crate) fn new(inner: BaseType) -> Self { + Self { + nullable: false, + unique: false, + increments: false, + indexed: false, + primary: false, + default: None, + size: None, + inner, + } + } + + /// Function used to hide the inner type to outside users (sneaky, I know) + pub(crate) fn get_inner(&self) -> BaseType { + self.inner.clone() + } + + /// Set the nullability of this type + pub fn nullable(self, arg: bool) -> Self { + Self { nullable: arg, ..self } + } + + /// Set the uniqueness of this type + pub fn unique(self, arg: bool) -> Self { + Self { unique: arg, ..self } + } + + /// Specify if this type should auto-increment + pub fn increments(self, arg: bool) -> Self { + Self { increments: arg, ..self } + } + + /// Specify if this type should be indexed by your SQL implementation + pub fn indexed(self, arg: bool) -> Self { + Self { indexed: arg, ..self } + } + + /// Specify if this type should be a primary key + pub fn primary(self, arg: bool) -> Self { + Self { primary: arg, ..self } + } + + /// Provide a default value for a type column + pub fn default(self, arg: impl Into<WrappedDefault<'static>>) -> Self { + Self { default: Some(arg.into()), ..self } + } + + /// Specify a size limit (important or varchar & similar) + pub fn size(self, arg: usize) -> Self { + Self { size: Some(arg), ..self } + } +} + +impl<'a> From<&'a str> for WrapVec<String> { + fn from(s: &'a str) -> Self { + WrapVec(vec![s.into()]) + } +} + +impl From<String> for WrapVec<String> { + fn from(s: String) -> Self { + WrapVec(vec![s]) + } +} + +impl<I> From<Vec<I>> for WrapVec<String> +where + I: Into<String>, +{ + fn from(v: Vec<I>) -> Self { + WrapVec(v.into_iter().map(|s| s.into()).collect()) + } +} |