dquery ~master
A neat little wrapper for convenient type information in D.
To use this package, run the following command in your project's root directory:
Manual usage
Put the following dependency into your project's dependences section:
dquery - Chainable compile-time metaprogramming
dquery is a light helper for processing types, traits, and other information at compile time. It provides filtering, mapping, iteration, and validation functions for queried types and members.
Example Code
Here's a little demo class we're going to query in these examples. Assume the types for @Id
and @Column
are structs defined elsewhere.
class User
{
@Id
@Column
ulong id;
@Column
string username;
@Column("email_address")
string email;
}
Queries
The query!()
template function produces a query for a type. This is the starting point for every dquery chain.
auto elements = query!User;
You can also query a type from a value via the query()
function, shown here using UFCS.
User user = new User;
auto elements = user.query;
Simple Filters
dquery provides filters for the 5 common types of members defined in types; fields, functions, constructors, destructors, and aggregates.
// Filter fields in User.
auto fields = query!User.fields;
// Filter functions in User.
auto functions = query!User.functions;
// Filter constructors in User.
auto constructors = query!User.constructors;
// Filter destructors in User.
auto destructors = query!User.destructors;
// Filter inner types in User.
auto aggregates = query!User.aggregates;
You also get a number of filters for common information about elements of a types, such as filters for names, types, return types, arity, parameter lists, etc.
query!Type
// Filter only names,
.names!("foo", "bar")
// Filter types,
.types!(int, string, bool)
// Filter return types,
.returns!(int, string, bool)
// Filter accessible elements,
.accessible
// Filter arities,
.arities!(0, 1, 2)
// Filter functions that take (int, string, bool),
.parameters!(int, string, bool)
// Filter elements that have @A and @B and @C,
.allOf!(A, B, C)
// Filter elements that have @A or @B or @C,
.anyOf!(A, B, C)
// Filter elements that don't have @A or @B or @C,
.noneOf!(A, B, C);
Simple Attribute Information
Easily check for attributes on any type or element.
auto userQuery = query!User;
// True if type User has @A and @B and @C.
bool hasAll = userQuery.hasAllOf!(A, B, C);
// True if type User has @A or @B or @C.
bool hasAny = userQuery.hasAnyOf!(A, B, C);
// True if type User has none of @A or @B or @C.
bool hasNone = userQuery.hasNoneOf!(A, B, C);
// Returns attributes attached to the User type.
auto attributes = query!User.attributes;
Transformations
dquery includes a filter!()
for custom or advanced filtering in chains.
auto elements =
query!User
// Custom filter.
.filter!(element =>
element.isTypeOf!string ||
element.hasAttribute!Id
);
dquery also includes a map!()
transform function for transforming the result of a chain.
string[] names =
query!User
// Filter fields,
.fields
// That have @Id or @Column,
.anyOf!(Id, Column)
// Map to their names.
.map!(field => field.name);
All dquery transform functions can take a function or delegate, or a template.
Simple Validations
dquery also provides simple functions to perform validations without breaking chains.
auto elements =
query!User
// Filter fields,
.fields
// That have @Id and @Column,
.allOf!(Id, Column)
// Ensure exactly 1 exists.
.ensure!"length"
.exactly!(1, "User needs exactly 1 @Id.");
Chaining Logic
dquery focuses on chaining so that complex logic can be broken down into simple sequences like,
auto elements =
query!User
// Filter constructors,
.constructors
// With arity 0,
.arity!(0)
// Ensure at least 1 exists,
.ensure!"length"
.minimum!(1, "User needs a 0 argument constructor.")
// Clear filters,
.reset
// Filter constructors,
.constructors
// That accept User,
.parameters!(User)
// Ensure none exist.
.ensure!"length"
.maximum!(0, "User must not define a copy constructor.");
Loops and Iteration
Query results can be iterated over with a foreach
.
foreach(element; elements)
{
static if(element.isTypeOf!string)
{
// Handle fields.
}
else
{
// Do something else.
}
}
You can also use the each!()
template function to iterate over results without breaking a chain.
auto elements =
query!User
// Filter fields,
.fields
// That have @Id or @Column,
.anyOf!(Id, Column)
// Ensure at least 1 exists.
.ensure!"length"
.minimum!(1, "User needs at least 1 @Id or @Column.")
// Do something for each,
.each!(
field => doSomething(field)
)
// Keep going...
.reset;
Joining Results
Mutliple chains can be joined together to produce even more complex queries easily.
auto elements =
query!User
// Filter fields,
.fields
// That have @Id or @Column,
.anyOf!(Id, Column)
// And are a string,
.types!string
// Join with,
.join(
query!User
// Filter functions,
.functions
// With both @Column and @Mappable,
.allOf!(Column, Mappable)
// And arity 0,
.arity!0
// That return a string.
.returns!string
);
You can also use a query's unique
property to remove any duplicate elements.
Attributes
dquery also provides functions for handling attributes attached to queried types and elements.
// Iterate over the list of elements,
foreach(element; elements)
{
// Iterate over each attribute that is a @Column,
foreach(attribute; element.attributes!Column)
{
// Get value of attribute, or use a fallback if it's a type.
Column column = attribute.getOrElse!(Column(element.name));
// . . .
}
}
In addition to getOrElse!(Default)
, attributes provide a get
method (defined only for expressions), and a getOrThrow!(Exception)
which throws an exception at runtime if the attribute is not an expression.
Limitations
Because of how traits are setup in D, dquery can't operate on private or protected types, fields, or functions. Inaccessible members only provide limited information.
License
MIT
- Registered by Mihail K
- ~master released 9 years ago
- mintyfresh/dquery
- MIT
- Copyright © 2015, Mihail-K
- Authors:
- Dependencies:
- none
- Versions:
-
0.1.8 2015-Sep-29 0.1.7 2015-Sep-29 0.1.6 2015-Jul-18 0.1.5 2015-Jul-13 0.1.4 2015-Jul-11 - Download Stats:
-
-
0 downloads today
-
0 downloads this week
-
0 downloads this month
-
344 downloads total
-
- Score:
- 1.4
- Short URL:
- dquery.dub.pm