#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct PColor(u8);
#[derive(Default)]
struct Pico8 {
last: Vec<&'static str>,
}
#[derive(Debug, Default, PartialEq, Eq)]
struct MyInput(u8);
impl From<u8> for MyInput {
fn from(x: u8) -> Self {
Self(x)
}
}
impl Pico8 {
fn sset(
&mut self,
_pos: (u32, u32),
_color: Option<PColor>,
_sheet_index: Option<usize>,
) -> Result<(), ()> {
self.last.push("sset");
Ok(())
}
fn sspr(&mut self, _pos: (u32, u32), _color: Option<PColor>) -> Result<(), ()> {
self.last.push("sspr");
Ok(())
}
}
fn prnt(_pos: (u32, u32), _color: Option<PColor>, input: MyInput) -> MyInput {
input
}
bobtail::define! {
sset_macro_one => fn sset(
&mut self,
pos: (u32, u32),
#[tail]
color: Option<PColor>,
sheet_index: Option<usize>,
) -> Result<(), ()>;
}
bobtail::define! {
fn sspr(
&mut self,
pos: (u32, u32),
#[tail]
color: Option<PColor>,
) -> Result<(), ()>;
}
bobtail::define! {
fn prnt(
pos: (u32, u32),
#[tail]
color: Option<PColor>,
_input: MyInput,
);
}
bobtail::define! {
sset_macro_all => fn sset(
&mut self,
pos: (u32, u32),
#[tail]
color: Option<PColor>,
sheet_index: Option<usize>,
) -> Result<(), ()>;
sspr_all => fn sspr(
&mut self,
pos: (u32, u32),
#[tail]
color: Option<PColor>,
) -> Result<(), ()>;
prnt_all => fn prnt(
pos: (u32, u32),
#[tail]
color: Option<PColor>,
_input: MyInput,
);
prnt_any => fn prnt(
pos: (u32, u32),
color: Option<PColor>,
_input: MyInput,
);
}
#[test]
fn tail_define_individual_method_with_explicit_macro_name() {
let mut pico = Pico8::default();
sset_macro_one!(pico, (0, 0)).unwrap();
sset_macro_one!(pico, (0, 0), PColor(1)).unwrap();
sset_macro_one!(pico, (0, 0), None, 3usize).unwrap();
assert_eq!(pico.last, vec!["sset", "sset", "sset"]);
}
#[test]
fn tail_define_individual_method_with_implicit_macro_name() {
let mut pico = Pico8::default();
sspr!(pico, (1, 2)).unwrap();
sspr!(pico, (1, 2), PColor(9)).unwrap();
assert_eq!(pico.last, vec!["sspr", "sspr"]);
}
#[test]
fn tail_define_individual_free_function() {
let x = MyInput(0);
assert_eq!(prnt!((0, 0)), x);
assert_eq!(prnt!((0, 0), PColor(7)), x);
assert_eq!(prnt!((0, 0), PColor(7), 8u8), MyInput(8));
assert_eq!(prnt!((0, 0), PColor(7), MyInput(9)), MyInput(9));
assert_eq!(prnt!((0, 0), PColor(7), MyInput(9),), MyInput(9));
assert_eq!(prnt_all!((0, 0), PColor(7), MyInput(9)), MyInput(9));
assert_eq!(prnt_all!((0, 0), PColor(7), MyInput::default()), MyInput(0));
assert_eq!(prnt_all!((0, 0), PColor(7), MyInput::default()), MyInput(0));
assert_eq!(
prnt_any!((0, 0), Some(PColor(7)), Default::default()),
MyInput(0)
);
}
#[test]
fn tail_define_all_together() {
let x = MyInput(0);
let mut pico = Pico8::default();
sset_macro_all!(pico, (0, 0)).unwrap();
sspr_all!(pico, (1, 2)).unwrap();
assert_eq!(prnt_all!((9, 9)), x);
assert_eq!(prnt!((9, 9)), x);
assert_eq!(pico.last, vec!["sset", "sspr"]);
}
#[cfg(feature = "omit-token")]
mod omit_token_tests {
use super::*;
#[test]
fn test_underscore_placeholder_method() {
let mut pico = Pico8::default();
sset_macro_one!(pico, (0, 0), _, 3usize).unwrap();
assert_eq!(pico.last, vec!["sset"]);
}
#[test]
fn test_underscore_placeholder_function() {
assert_eq!(prnt_all!((0, 0), PColor(7), _), MyInput(0));
assert_eq!(prnt_all!((0, 0), PColor(7), _,), MyInput(0));
}
}
mod visibility_tests {
fn vis_helper(a: u8, b: Option<u8>) -> u8 {
b.map(|x| x + a).unwrap_or(a)
}
bobtail::define! {
vis_helper_crate => fn vis_helper(a: u8, #[tail] b: Option<u8>) -> u8;
}
#[test]
fn test_pub_crate_visibility_with_name() {
assert_eq!(vis_helper_crate!(1), 1);
assert_eq!(vis_helper_crate!(1, 2u8), 3);
}
mod inner_private {
fn inner_helper(a: u8, b: Option<u8>) -> u8 {
b.map(|x| x + a).unwrap_or(a)
}
bobtail::define! {
pub(self) private_macro => fn inner_helper(a: u8, #[tail] b: Option<u8>) -> u8;
}
pub fn use_private_macro() -> u8 {
private_macro!(5)
}
}
#[test]
fn test_pub_self_private_macro() {
assert_eq!(inner_private::use_private_macro(), 5);
}
mod vis_only_inner {
pub fn my_add(a: u8, b: Option<u8>) -> u8 {
b.map(|x| x + a).unwrap_or(a)
}
bobtail::define! {
pub(crate) my_add_macro => fn my_add(a: u8, #[tail] b: Option<u8>) -> u8;
}
pub fn test_internally() -> u8 {
my_add_macro!(10)
}
}
#[test]
fn test_pub_crate_visibility_only() {
assert_eq!(vis_only_inner::test_internally(), 10);
use vis_only_inner::{my_add, my_add_macro};
assert_eq!(my_add_macro!(1), 1);
assert_eq!(my_add_macro!(1, 2u8), 3);
}
mod inherit_vis_test {
pub(crate) fn my_fn(a: u8, b: Option<u8>) -> u8 {
b.map(|x| x + a).unwrap_or(a)
}
bobtail::define! {
pub(crate) vis_macro => fn my_fn(a: u8, #[tail] b: Option<u8>) -> u8;
}
bobtail::define! {
private_macro => fn my_fn(a: u8, #[tail] b: Option<u8>) -> u8;
}
pub fn use_private_macro() -> u8 {
private_macro!(7)
}
}
#[test]
fn test_visibility_before_macro_name() {
use inherit_vis_test::{my_fn, vis_macro};
assert_eq!(vis_macro!(5), 5);
assert_eq!(vis_macro!(5, 3u8), 8);
assert_eq!(inherit_vis_test::use_private_macro(), 7);
}
}
mod typeless_params {
fn add(a: u8, b: Option<u8>) -> u8 {
b.map(|x| x + a).unwrap_or(a)
}
bobtail::define! {
typeless_add => fn add(a, #[tail] b);
}
#[test]
fn test_typeless_define() {
assert_eq!(typeless_add!(5), 5);
assert_eq!(typeless_add!(5, 3u8), 8);
}
}