Skip to content

Commit

Permalink
v0.8.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Colonial-Dev committed Oct 25, 2023
1 parent 97b9f33 commit fc60de8
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### v0.8.0
- (Improvement, **breaking**) The `record` macro no longer derives `Debug` and `Clone`, but now accepts custom attributes (such as derives and doc comments) similar to `sql_enum`.
- Added some additional doc examples.

### v0.7.1
- (Improvement) Tests generated by the `#[check(...)]` attribute now verify that there are no columns that exist in the schema but not in the model. (Previously, it only checked in one direction - verifying that all fields of the model existed in the schema.)
- (Improvement) The `sql_enum` macro now accepts an optional `Type` parameter that can be used to specify the discriminant type. By default, `i64` is still used.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ members = [
]

[workspace.package]
version = "0.7.1"
version = "0.8.0"
authors = ["Colonial"]
edition = "2021"
license = "MIT OR Apache-2.0"
Expand Down
81 changes: 74 additions & 7 deletions exemplar/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
///
/// # Requirements
///
/// [`Model`](crate::Model) can *only* be derived for `struct`s with suitable named fields.
/// [`Model`](crate::Model) can *only* be derived for non-generic `struct`s with suitable named fields.
///
/// | Type | Example | Supported? |
/// | ---- | ------- | ---------- |
/// | Standard `struct` | `struct Person { name: String }` | ✔ |
/// | Generic `struct` | `struct Person<'a, T, const N: usize> { ... }` | ✘ |
/// | Tuple struct | `struct Point(i64, i64)` | ✘ |
/// | Unit/ZST struct | `struct Unit;` or `struct Unit {}` | ✘ |
/// | `enum`s | `enum Direction { Up, Down }` | ✘ |
Expand Down Expand Up @@ -64,7 +65,7 @@
///
/// More specifically, the generated test verifies that:
/// - The specified table exists.
/// - All specified columns/fields exist.
/// - The columns in the schema match up with those specified by the model type. If the model has fields not present in the schema (or vice versa) the test will fail.
///
/// It does *not* verify the validity of column types, nor does it test actual insertion/retrieval.
///
Expand All @@ -86,6 +87,32 @@
///
/// In both cases `T` is the type of the field being annotated. For some types (e.g. `PathBuf`) you may also be able to use a type it derefs to, like `Path`.
///
/// Example implementations for `PathBuf`:
/// ```rust
/// # use exemplar::*;
/// # use std::path::{Path, PathBuf};
/// # use rusqlite::types::ValueRef;
/// pub fn bind_path(value: &Path) -> BindResult {
/// use rusqlite::types::Value;
/// use rusqlite::types::ToSqlOutput;
///
/// // Depending on your program, it may make more sense
/// // to error if a lossless conversion isn't possible.
/// let str = value.to_string_lossy().into_owned();
///
/// Ok(ToSqlOutput::Owned(
/// Value::Text(str)
/// ))
/// }
///
/// pub fn extr_path(value: &ValueRef) -> ExtrResult<PathBuf> {
/// let path = value.as_str()?;
/// let path = PathBuf::from(path);
///
/// Ok(path)
/// }
/// ```
///
/// ### `#[column]`
/// Usage:
/// ```ignore
Expand Down Expand Up @@ -139,13 +166,51 @@ pub use exemplar_proc_macro::Model;
/// .query_and_then([], Age::from_row)?
/// .map(|age| ...);
/// ```
///
/// # Notes
///
/// Doc comments (and other attributes) are supported:
/// ```rust
/// # use exemplar::*;
/// record! {
/// /// A person's name.
/// name => String,
/// /// A person's age.
/// age => u16,
/// }
/// ```
/// Additionally, you can apply type-level attributes like derives on the `Name` argument.
/// ```rust
/// # use exemplar::*;
/// record! {
/// #[derive(Debug, Clone)]
/// Name => Age,
/// age => u16,
/// }
/// ```
/// (`record!` does not apply any derives automatically.)
///
/// This does *not* work without the `Name` argument, due to macro limitations - Rust can't
/// disambiguate between "attributes for the struct" and "attributes for the field."
///
/// ```compile_fail
/// # use exemplar::*;
/// record! {
/// #[derive(Debug, Clone)]
/// /// A person's name.
/// name => String,
/// /// A person's age.
/// age => u16,
/// }
/// ```
#[macro_export]
macro_rules! record {
(Name => $name:ident, $($fname:ident => $ftype:ty),* $(,)?) => {
#[derive(Debug, Clone)]
($(#[$struct_doc:meta])* Name => $name:ident, $($(#[$field_doc:meta])* $fname:ident => $ftype:ty),* $(,)?) => {
$(#[$struct_doc])*
///
/// Automatically generated record type for storing query results.
pub struct $name {
$(pub $fname : $ftype),*
$($(#[$field_doc])* pub $fname : $ftype),*
}

impl $name {
Expand All @@ -164,8 +229,8 @@ macro_rules! record {
}
}
};
($($fname:ident => $ftype:ty),* $(,)?) => {
record!(Name => Record, $($fname => $ftype),*);
($($(#[$field_doc:meta])* $fname:ident => $ftype:ty),* $(,)?) => {
record!(Name => Record, $($(#[$field_doc])* $fname => $ftype),*);
};
}

Expand Down Expand Up @@ -225,9 +290,11 @@ macro_rules! record {
/// ```rust
/// # use exemplar::sql_enum;
/// sql_enum! {
/// #[derive(Default)]
/// /// An RGB color tag.
/// Name => Color,
/// /// Red
/// #[default]
/// Red,
/// /// Green
/// Green,
Expand Down

0 comments on commit fc60de8

Please sign in to comment.