Skip to content

Commit

Permalink
Introduce @value implementation + avoid imports in @EqualsAndHashCode
Browse files Browse the repository at this point in the history
…implementation
  • Loading branch information
mikhael-sokolov-rs committed Aug 15, 2023
1 parent a4c3ac3 commit 5128407
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 32 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "lombok"
version = "0.3.4"
version = "0.4.0"
description = "Lombok port for Rust"
authors = ["sokomishalov <[email protected]>"]
edition = "2021"
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

Just because I can!

This crate is not actually the must-have one for development in Rust (unlike Java world), but if you find it useful - it
would be great. Anyway - boilerplate sucks, so get some proc macros stuff for decrease it.
This crate is not actually a must-have one for development in Rust (unlike Java world), but if you find it useful - it
would be great. Anyway - boilerplate sucks, so get some proc macros stuff to decrease it.

Any feedback is appreciated.

Expand All @@ -22,6 +22,7 @@ Any feedback is appreciated.
- [x] `@EqualsAndHashCode` - `#[derive(EqualsAndHashCode)]`
- [x] `@ToString` - `#[derive(ToString)]`
- [x] `@Data` - `#[derive(Data)]`
- [x] `@Value` - `#[derive(Value)]`
- [x] `@NoArgsConstructor` - `#[derive(NoArgsConstructor)]`
- [x] `@AllArgsConstructor` - `#[derive(AllArgsConstructor)]`
- [x] `@Builder` - `#[derive(Builder)]`
Expand All @@ -32,7 +33,7 @@ Update `Cargo.toml`

```toml
[dependencies]
lombok = "0.3"
lombok = "0.4"
```

Source code usage examples you can see [in tests](./tests/tests.rs).
Expand Down
6 changes: 2 additions & 4 deletions src/equals_and_hash_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,15 @@ pub(crate) fn equals_and_hash_code(input: TokenStream) -> TokenStream {
});

TokenStream::from(quote! {
use std::hash::{Hash, Hasher};

impl #impl_generics #name #ty_generics #where_clause {
fn equals(&self, other: &#name #ty_generics) -> bool {
self.eq(&other)
}

fn hash_code(&self) -> u64 {
let mut hasher = ::std::collections::hash_map::DefaultHasher::new();
&self.hash(&mut hasher);
hasher.finish()
::std::hash::Hash::hash(&self, &mut hasher);
::std::hash::Hasher::finish(&hasher)
}
}

Expand Down
13 changes: 13 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,16 @@ pub fn derive_data(input: TokenStream) -> TokenStream {
.into_iter(),
)
}

#[proc_macro_derive(Value)]
pub fn derive_value(input: TokenStream) -> TokenStream {
TokenStream::from_iter(
vec![
getter(input.clone()),
all_args_constructor(input.clone()),
equals_and_hash_code(input.clone()),
to_string(input),
]
.into_iter(),
)
}
87 changes: 63 additions & 24 deletions tests/tests.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use lombok::{
AllArgsConstructor, Builder, EqualsAndHashCode, Getter, GetterMut, NoArgsConstructor, Setter,
ToString,
AllArgsConstructor, Builder, Data, EqualsAndHashCode, Getter, GetterMut, NoArgsConstructor,
Setter, ToString, Value,
};

#[derive(
Expand All @@ -14,21 +14,33 @@ use lombok::{
ToString,
Clone,
)]
pub struct TestNamedStructure<'a> {
pub struct TestFullFeaturedStructure<'a> {
age: u8,
nick: &'a str,
languages: Vec<String>,
hobby: Box<&'a str>,
}

#[derive(Data)]
struct TestDataStructure<'a> {
age: u8,
nick: &'a str,
}

#[derive(Value)]
struct TestValueStructure<'a> {
age: u8,
nick: &'a str,
}

#[cfg(test)]
#[allow(dead_code)]
mod tests {
use crate::TestNamedStructure;
use crate::{TestDataStructure, TestFullFeaturedStructure, TestValueStructure};

#[test]
fn test_getter() {
let default = TestNamedStructure::default();
let default = TestFullFeaturedStructure::default();

assert_eq!(&default.age, default.get_age());
assert_eq!(default.nick, default.get_nick());
Expand All @@ -38,13 +50,13 @@ mod tests {

#[test]
fn test_getter_mut() {
let mut default = TestNamedStructure::default();
let mut default = TestFullFeaturedStructure::default();
*default.get_age_mut() = 10;
*default.get_nick_mut() = "another";
*default.get_languages_mut() = vec!["python".to_string()];
*default.get_hobby_mut() = Box::new("tennis");

let copy = TestNamedStructure::default();
let copy = TestFullFeaturedStructure::default();

assert_ne!(copy.age, default.age);
assert_ne!(copy.nick, default.nick);
Expand All @@ -54,14 +66,14 @@ mod tests {

#[test]
fn test_setter() {
let mut data = TestNamedStructure {
let mut data = TestFullFeaturedStructure {
age: Default::default(),
nick: Default::default(),
languages: Default::default(),
hobby: Default::default(),
};

let default = TestNamedStructure::default();
let default = TestFullFeaturedStructure::default();
let clone_default = default.clone();

data.set_age(clone_default.age);
Expand All @@ -77,9 +89,9 @@ mod tests {

#[test]
fn test_no_args_constructor() {
let mut data = TestNamedStructure::new_default();
let mut data = TestFullFeaturedStructure::new_default();

let default = TestNamedStructure::default();
let default = TestFullFeaturedStructure::default();
let clone_default = default.clone();

data.set_age(clone_default.age);
Expand All @@ -95,10 +107,10 @@ mod tests {

#[test]
fn test_all_args_constructor() {
let default = TestNamedStructure::default();
let default = TestFullFeaturedStructure::default();
let clone_default = default.clone();

let data = TestNamedStructure::new(
let data = TestFullFeaturedStructure::new(
clone_default.age,
clone_default.nick,
clone_default.languages,
Expand All @@ -113,34 +125,36 @@ mod tests {

#[test]
fn test_equals_and_hashcode() {
let default = TestNamedStructure::default();
let mut clone_default = default.clone();
let default = TestFullFeaturedStructure::default();
let mut adjusted_default = default.clone();

assert!(&default.equals(&clone_default));
assert_eq!(&default.hash_code(), &clone_default.hash_code());
assert!(&default.equals(&adjusted_default));
assert_eq!(&default.hash_code(), &adjusted_default.hash_code());

clone_default.age = 10;
adjusted_default.age = 10;

assert!(!&default.equals(&clone_default));
assert_ne!(&default.hash_code(), &clone_default.hash_code());
assert!(!&default.equals(&adjusted_default));
assert_ne!(&default.hash_code(), &adjusted_default.hash_code());
}

#[test]
fn test_to_string() {
let default = TestNamedStructure::default();
let default = TestFullFeaturedStructure::default();
let string = default.to_string();
assert_eq!(
String::from("TestNamedStructure { age: 0, nick: \"\", languages: [], hobby: \"\" }"),
String::from(
"TestFullFeaturedStructure { age: 0, nick: \"\", languages: [], hobby: \"\" }"
),
string
)
}

#[test]
fn test_builder() {
let default = TestNamedStructure::default();
let default = TestFullFeaturedStructure::default();
let clone_default = default.clone();

let data = TestNamedStructure::builder()
let data = TestFullFeaturedStructure::builder()
.age(clone_default.age)
.nick(clone_default.nick)
.languages(clone_default.languages)
Expand All @@ -149,4 +163,29 @@ mod tests {

assert_eq!(&default, &data);
}

#[test]
fn test_data() {
let mut data = TestDataStructure::new(28, "sokomishalov");

data.set_age(29);

assert_eq!(29, *data.get_age());
assert_eq!("sokomishalov", data.get_nick());
assert_eq!(
String::from("TestDataStructure { age: 29, nick: \"sokomishalov\" }"),
data.to_string()
)
}

#[test]
fn test_value() {
let value = TestValueStructure::new(28, "sokomishalov");

assert_eq!(28, *value.get_age());
assert_eq!(
String::from("TestValueStructure { age: 28, nick: \"sokomishalov\" }"),
value.to_string()
)
}
}

0 comments on commit 5128407

Please sign in to comment.