use std::marker::PhantomData;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum LoadingStrategy {
#[default]
Lazy,
Eager,
SelectIn,
Joined,
Subquery,
}
#[derive(Debug, Clone)]
pub struct LazyLoader<T> {
_phantom: PhantomData<T>,
}
impl<T> LazyLoader<T> {
pub fn new() -> Self {
Self {
_phantom: PhantomData,
}
}
}
impl<T> Default for LazyLoader<T> {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct EagerLoader<T> {
pub strategy: LoadingStrategy,
_phantom: PhantomData<T>,
}
impl<T> EagerLoader<T> {
pub fn new() -> Self {
Self {
strategy: LoadingStrategy::SelectIn,
_phantom: PhantomData,
}
}
pub fn with_strategy(strategy: LoadingStrategy) -> Self {
Self {
strategy,
_phantom: PhantomData,
}
}
pub fn strategy(&self) -> LoadingStrategy {
self.strategy
}
}
impl<T> Default for EagerLoader<T> {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct SelectInLoader<T> {
pub batch_size: Option<usize>,
_phantom: PhantomData<T>,
}
impl<T> SelectInLoader<T> {
pub fn new() -> Self {
Self {
batch_size: None,
_phantom: PhantomData,
}
}
pub fn batch_size(mut self, size: usize) -> Self {
self.batch_size = Some(size);
self
}
pub fn get_batch_size(&self) -> Option<usize> {
self.batch_size
}
}
impl<T> Default for SelectInLoader<T> {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct JoinedLoader<T> {
pub outer_join: bool,
_phantom: PhantomData<T>,
}
impl<T> JoinedLoader<T> {
pub fn new() -> Self {
Self {
outer_join: false,
_phantom: PhantomData,
}
}
pub fn outer() -> Self {
Self {
outer_join: true,
_phantom: PhantomData,
}
}
pub fn is_outer_join(&self) -> bool {
self.outer_join
}
}
impl<T> Default for JoinedLoader<T> {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[allow(dead_code)]
#[derive(Clone)]
struct Post {
id: i64,
author_id: i64,
title: String,
}
#[test]
fn test_loading_strategy_default() {
assert_eq!(LoadingStrategy::default(), LoadingStrategy::Lazy);
}
#[test]
fn test_loading_strategies() {
let strategies = vec![
LoadingStrategy::Lazy,
LoadingStrategy::Eager,
LoadingStrategy::SelectIn,
LoadingStrategy::Joined,
LoadingStrategy::Subquery,
];
for strategy in strategies {
assert_eq!(strategy, strategy);
}
}
#[test]
fn test_lazy_loader_creation() {
let _loader: LazyLoader<Post> = LazyLoader::new();
let _loader2: LazyLoader<Post> = LazyLoader::default();
}
#[test]
fn test_eager_loader_creation() {
let loader: EagerLoader<Post> = EagerLoader::new();
assert_eq!(loader.strategy(), LoadingStrategy::SelectIn);
}
#[test]
fn test_eager_loader_with_strategy() {
let loader: EagerLoader<Post> = EagerLoader::with_strategy(LoadingStrategy::Joined);
assert_eq!(loader.strategy(), LoadingStrategy::Joined);
let loader2: EagerLoader<Post> = EagerLoader::with_strategy(LoadingStrategy::Subquery);
assert_eq!(loader2.strategy(), LoadingStrategy::Subquery);
}
#[test]
fn test_select_in_loader_creation() {
let loader: SelectInLoader<Post> = SelectInLoader::new();
assert_eq!(loader.get_batch_size(), None);
}
#[test]
fn test_select_in_loader_batch_size() {
let loader: SelectInLoader<Post> = SelectInLoader::new().batch_size(100);
assert_eq!(loader.get_batch_size(), Some(100));
let loader2: SelectInLoader<Post> = SelectInLoader::new().batch_size(500);
assert_eq!(loader2.get_batch_size(), Some(500));
}
#[test]
fn test_joined_loader_creation() {
let loader: JoinedLoader<Post> = JoinedLoader::new();
assert!(!loader.is_outer_join());
}
#[test]
fn test_joined_loader_outer() {
let loader: JoinedLoader<Post> = JoinedLoader::outer();
assert!(loader.is_outer_join());
}
#[test]
fn test_joined_loader_inner() {
let loader: JoinedLoader<Post> = JoinedLoader::new();
assert!(!loader.is_outer_join());
}
}