You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
4.4 KiB
165 lines
4.4 KiB
//! 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())
|
|
}
|
|
}
|
|
|