Skip to content

Commit

Permalink
Add .value() methods, update documentation, minor changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcin Sas-Szymański committed Jul 1, 2024
1 parent 546e702 commit fb872ff
Show file tree
Hide file tree
Showing 13 changed files with 252 additions and 45 deletions.
79 changes: 71 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ You can customize which traits are implemented or skipped using the `#[synonym(s
pub struct MyString(String);
```

Supported `skip` and `force` values are listed in the *Trait implementation table* below.

## Generated code
When you use `#[derive(Synonym)]`, the library generates implementations for various traits. Here's a simplified example for a newtype `MyInt(i32)`:
```rust
Expand All @@ -55,14 +57,75 @@ impl PartialEq for MyInt {

## Trait implementation table

| Kind | Traits / Methods Implemented |
| ------- | ---------------------------- |
| Integer<br>`u8`, `u16`, `u32`, `u64`, `u128`, `usize`,<br>`i8`, `i16`, `i32`, `i64`, `i128`, `isize` | `Eq`, `PartialEq`, `Ord`, `PartialOrd`, `Clone`, `Copy`, `Hash`, `Default`, `Debug`, `Add`, `Sub`, `Mul`, `Div`, `AddAssign`, `SubAssign`, `MulAssign`, `DivAssign`, `FromStr`, `From`, `AsRef`, `Deref` |
| Integer<br>`NonZeroU8`, `NonZeroU16`, `NonZeroU32`, `NonZeroU64`, `NonZeroU128`, `NonZeroUsize`,<br>`NonZeroI8`, `NonZeroI16`, `NonZeroI32`, `NonZeroI64`, `NonZeroI128`, `NonZeroIsize` | `Eq`, `PartialEq`, `Ord`, `PartialOrd`, `Clone`, `Copy`, `Hash`, `Debug`, `FromStr`, `From`, `AsRef`, `Deref` |
| Float<br>`f32`, `f64` | `PartialEq`, `PartialOrd`, `Clone`, `Default`, `Debug`, `Add`, `Sub`, `Mul`, `Div`, `AddAssign`, `SubAssign`, `MulAssign`, `DivAssign`, `FromStr`, `From`, `AsRef`, `Deref` |
| String<br>`String`, `Box<str>` | `Eq`, `PartialEq`, `Ord`, `PartialOrd`, `Clone`, `Hash`, `Default`, `Debug`, `FromStr`, `From`, `AsRef`, `Deref`, `Borrow<str>`, `as_str()` |
| String<br>`&'static str` | `Eq`, `PartialEq`, `Ord`, `PartialOrd`, `Clone`, `Hash`, `Default`, `Debug`, `From`, `AsRef`, `Deref`, `Borrow<str>`, `as_str()` |
| Char<br>`char` | `Eq`, `PartialEq`, `Ord`, `PartialOrd`, `Clone`, `Copy`, `Hash`, `Default`, `Debug`, `FromStr`, `From`, `AsRef`, `Deref` |
Custom methods

| | skip/force | `Integer` [1] | `NonZero*` | `Float` | `String` | `Box<str>` | `&'static str` | `char` |
|------------------|-------------|---------------|------------|---------|----------|------------|----------------|--------|
| .as_str() | String | | | | v | v | v | v |
| .value() [2] | Value | v | v | v | v | v | v | v |


Conversion

| | skip/force | `Integer` [1] | `NonZero*` | `Float` | `String` | `Box<str>` | `&'static str` | `char` |
|------------------|-------------|---------------|------------|---------|----------|------------|----------------|--------|
| AsRef<Inner> | AsRef | v | v | v | v | v | v | v |
| Borrow<str> | String | | | | v | v | v | |
| From<&'a str> | String | | | | v | v [4] | | |
| From<String> | String | | | | | v | | |
| Deref<Inner> [3] | Deref | | | | | | | |
| DerefMut [3] | DerefMut | | | | | | | |
| From<Inner> | From | v | v | v | v | v | v | v |
| FromStr | FromStr | v | v | v | v | v | | v |

Fundamental traits

| | skip/force | `Integer` [1] | `NonZero*` | `Float` | `String` | `Box<str>` | `&'static str` | `char` |
|------------------|-------------|---------------|------------|---------|----------|------------|----------------|--------|
| Clone | Clone | v | v | v | v | v | v | v |
| Copy | Copy | v | v | v | | v | v |
| Debug | Debug | v | v | v | v | v | v | v |
| Default | Default | v | | v | v | v | v | v |
| Display [5] | Display | v | v | v | v | v | v | v |
| Hash | Hash | v | v | | v | v | v | v |

Comparison

| | skip/force | `Integer` [1] | `NonZero*` | `Float` | `String` | `Box<str>` | `&'static str` | `char` |
|------------------|-------------|---------------|------------|---------|----------|------------|----------------|--------|
| PartialOrd | PartialOrd | v | v | v | v | v | v | v |
| Ord | Ord | v | v | | v | v | v | v |
| PartialEq | PartialEq | v | v | v | v | v | v | v |
| Eq | Eq | v | v | | v | v | v | v |

Serde [6]

| | skip/force | `Integer` [1] | `NonZero*` | `Float` | `String` | `Box<str>` | `&'static str` | `char` |
|------------------|-------------|---------------|------------|---------|----------|------------|----------------|--------|
| Serialize | Serialize | v | v | v | v | v | | v |
| Deserialize | Deserialize | v | v | v | v | v | | v |

Maths [7]

| | skip/force | `Integer` [1] | `NonZero*` | `Float` | `String` | `Box<str>` | `&'static str` | `char` |
|------------------|-------------|---------------|------------|---------|----------|------------|----------------|--------|
| Add<Self>=Self | Number | v | | v | | | |
| AddAssign<Self> | Number | v | | v | | | |
| Sub<Self>=Self | Number | v | | v | | | |
| SubAssign<Self> | Number | v | | v | | | |
| Mul<Self>=Self | Number | v | | v | | | |
| MulAssign<Self> | Number | v | | v | | | |
| Div<Self>=Self | Number | v | | v | | | |
| DivAssign<Self> | Number | v | | v | | | |


[1] Integers are: `u8`, `u16`, `u32`, `u64`, `u128`, `usize`, `i8`, `i16`, `i32`, `i64`, `i128`, `isize`
[2] .value() returns `Inner` for `Copy` types and `&Inner` for non-`Copy` types
[3] `Deref` and `DerefMut` are never implemented unless they are forced with `#[synonym(force(deref,deref_mut))]`
[4] In constrast to other strings, `FromStr` for `Box<str>` synonyms uses `Inner::From<&'str>` instead of `Inner::FromStr` since there is no `FromStr` implementation for `Box<str>`
[5] Display implementation can be configured, see below
[6] Only provided when feature `with_serde` is enabled
[7] This is subject to change

## Fine-tuning

Expand Down
2 changes: 2 additions & 0 deletions src/attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ pub struct ImplList {
pub serialize: bool,
#[darling(rename = "Deserialize")]
pub deserialize: bool,
#[darling(rename = "Value")]
pub value: bool,
}

#[derive(Debug, FromMeta, Default)]
Expand Down
2 changes: 1 addition & 1 deletion src/impls/from_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub fn impl_from_str(info: &Info) -> proc_macro2::TokenStream {
type Err = ::core::convert::Infallible;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(s.to_owned().into_boxed_str()))
Ok(Self(s.into()))
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/impls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod from;
mod from_str;
mod number;
mod string;
mod value;

pub use self::as_ref::*;
pub use self::deref::*;
Expand All @@ -17,3 +18,4 @@ pub use self::from::*;
pub use self::from_str::*;
pub use self::number::*;
pub use self::string::*;
pub use self::value::*;
10 changes: 10 additions & 0 deletions src/impls/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ pub fn impl_string(info: &Info) -> proc_macro2::TokenStream {
});
}

if info.kind == Kind::BoxStr {
tokens.extend(quote! {
impl ::core::convert::From<String> for #name {
fn from(s: String) -> Self {
Self(s.into_boxed_str())
}
}
});
}

tokens
}

Expand Down
37 changes: 37 additions & 0 deletions src/impls/value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use crate::info::Info;
use quote::quote;

pub fn impl_value(info: &Info) -> proc_macro2::TokenStream {
if !is_value(info) {
return quote! {};
}

let name = &info.name;
let typ = &info.typ;

if info.kind.is_copy() || info.attrs.force.copy {
quote! {
impl #name {
pub fn value(&self) -> #typ {
self.0
}
}
}
} else {
quote! {
impl #name {
pub fn value(&self) -> &#typ {
&self.0
}
}
}
}
}

pub fn is_value(info: &Info) -> bool {
if info.attrs.skip.value {
return false;
}

true
}
6 changes: 4 additions & 2 deletions src/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ impl Kind {

pub fn is_copy(&self) -> bool {
match self {
Kind::Integer | Kind::NonZeroInteger | Kind::Float | Kind::Char => true,
Kind::String | Kind::BoxStr | Kind::StaticStr | Kind::Other => false,
Kind::Integer | Kind::NonZeroInteger | Kind::Float | Kind::Char | Kind::StaticStr => {
true
}
Kind::String | Kind::BoxStr | Kind::Other => false,
}
}

Expand Down
80 changes: 72 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
//! pub struct MyString(String);
//! ```
//!
//! Supported `skip` and `force` values are listed in the *Trait implementation table* below.
//!
//! # Generated code
//! When you use `#[derive(Synonym)]`, the library generates implementations for various traits. Here's a simplified example for a newtype `MyInt(i32)`:
//! ```rust
Expand All @@ -47,14 +49,75 @@
//!
//! # Trait implementation table
//!
//! | Kind | Traits / Methods Implemented |
//! | ------- | ---------------------------- |
//! | Integer<br>`u8`, `u16`, `u32`, `u64`, `u128`, `usize`,<br>`i8`, `i16`, `i32`, `i64`, `i128`, `isize` | `Eq`, `PartialEq`, `Ord`, `PartialOrd`, `Clone`, `Copy`, `Hash`, `Default`, `Debug`, `Add`, `Sub`, `Mul`, `Div`, `AddAssign`, `SubAssign`, `MulAssign`, `DivAssign`, `FromStr`, `From`, `AsRef`, `Deref` |
//! | Integer<br>`NonZeroU8`, `NonZeroU16`, `NonZeroU32`, `NonZeroU64`, `NonZeroU128`, `NonZeroUsize`,<br>`NonZeroI8`, `NonZeroI16`, `NonZeroI32`, `NonZeroI64`, `NonZeroI128`, `NonZeroIsize` | `Eq`, `PartialEq`, `Ord`, `PartialOrd`, `Clone`, `Copy`, `Hash`, `Debug`, `FromStr`, `From`, `AsRef`, `Deref` |
//! | Float<br>`f32`, `f64` | `PartialEq`, `PartialOrd`, `Clone`, `Default`, `Debug`, `Add`, `Sub`, `Mul`, `Div`, `AddAssign`, `SubAssign`, `MulAssign`, `DivAssign`, `FromStr`, `From`, `AsRef`, `Deref` |
//! | String<br>`String`, `Box<str>` | `Eq`, `PartialEq`, `Ord`, `PartialOrd`, `Clone`, `Hash`, `Default`, `Debug`, `FromStr`, `From`, `AsRef`, `Deref`, `Borrow<str>`, `as_str()` |
//! | String<br>`&'static str` | `Eq`, `PartialEq`, `Ord`, `PartialOrd`, `Clone`, `Hash`, `Default`, `Debug`, `From`, `AsRef`, `Deref`, `Borrow<str>`, `as_str()` |
//! | Char<br>`char` | `Eq`, `PartialEq`, `Ord`, `PartialOrd`, `Clone`, `Copy`, `Hash`, `Default`, `Debug`, `FromStr`, `From`, `AsRef`, `Deref` |
//! Custom methods
//!
//! | | skip/force | `Integer` [1] | `NonZero*` | `Float` | `String` | `Box<str>` | `&'static str` | `char` |
//! |------------------|-------------|---------------|------------|---------|----------|------------|----------------|--------|
//! | .as_str() | String | | | | v | v | v | v |
//! | .value() [2] | Value | v | v | v | v | v | v | v |
//!
//!
//! Conversion
//!
//! | | skip/force | `Integer` [1] | `NonZero*` | `Float` | `String` | `Box<str>` | `&'static str` | `char` |
//! |------------------|-------------|---------------|------------|---------|----------|------------|----------------|--------|
//! | AsRef<Inner> | AsRef | v | v | v | v | v | v | v |
//! | Borrow<str> | String | | | | v | v | v | |
//! | From<&'a str> | String | | | | v | v [4] | | |
//! | From<String> | String | | | | | v | | |
//! | Deref<Inner> [3] | Deref | | | | | | | |
//! | DerefMut [3] | DerefMut | | | | | | | |
//! | From<Inner> | From | v | v | v | v | v | v | v |
//! | FromStr | FromStr | v | v | v | v | v | | v |
//!
//! Fundamental traits
//!
//! | | skip/force | `Integer` [1] | `NonZero*` | `Float` | `String` | `Box<str>` | `&'static str` | `char` |
//! |------------------|-------------|---------------|------------|---------|----------|------------|----------------|--------|
//! | Clone | Clone | v | v | v | v | v | v | v |
//! | Copy | Copy | v | v | v | | v | v |
//! | Debug | Debug | v | v | v | v | v | v | v |
//! | Default | Default | v | | v | v | v | v | v |
//! | Display [5] | Display | v | v | v | v | v | v | v |
//! | Hash | Hash | v | v | | v | v | v | v |
//!
//! Comparison
//!
//! | | skip/force | `Integer` [1] | `NonZero*` | `Float` | `String` | `Box<str>` | `&'static str` | `char` |
//! |------------------|-------------|---------------|------------|---------|----------|------------|----------------|--------|
//! | PartialOrd | PartialOrd | v | v | v | v | v | v | v |
//! | Ord | Ord | v | v | | v | v | v | v |
//! | PartialEq | PartialEq | v | v | v | v | v | v | v |
//! | Eq | Eq | v | v | | v | v | v | v |
//!
//! Serde [6]
//!
//! | | skip/force | `Integer` [1] | `NonZero*` | `Float` | `String` | `Box<str>` | `&'static str` | `char` |
//! |------------------|-------------|---------------|------------|---------|----------|------------|----------------|--------|
//! | Serialize | Serialize | v | v | v | v | v | | v |
//! | Deserialize | Deserialize | v | v | v | v | v | | v |
//!
//! Maths [7]
//!
//! | | skip/force | `Integer` [1] | `NonZero*` | `Float` | `String` | `Box<str>` | `&'static str` | `char` |
//! |------------------|-------------|---------------|------------|---------|----------|------------|----------------|--------|
//! | Add<Self>=Self | Number | v | | v | | | |
//! | AddAssign<Self> | Number | v | | v | | | |
//! | Sub<Self>=Self | Number | v | | v | | | |
//! | SubAssign<Self> | Number | v | | v | | | |
//! | Mul<Self>=Self | Number | v | | v | | | |
//! | MulAssign<Self> | Number | v | | v | | | |
//! | Div<Self>=Self | Number | v | | v | | | |
//! | DivAssign<Self> | Number | v | | v | | | |
//!
//!
//! [1] Integers are: `u8`, `u16`, `u32`, `u64`, `u128`, `usize`, `i8`, `i16`, `i32`, `i64`, `i128`, `isize`
//! [2] .value() returns `Inner` for `Copy` types and `&Inner` for non-`Copy` types
//! [3] `Deref` and `DerefMut` are never implemented unless they are forced with `#[synonym(force(deref,deref_mut))]`
//! [4] In constrast to other strings, `FromStr` for `Box<str>` synonyms uses `Inner::From<&'str>` instead of `Inner::FromStr` since there is no `FromStr` implementation for `Box<str>`
//! [5] Display implementation can be configured, see below
//! [6] Only provided when feature `with_serde` is enabled
//! [7] This is subject to change
//!
//! # Fine-tuning
//!
Expand Down Expand Up @@ -133,6 +196,7 @@ pub fn synonym_derive(input: TokenStream) -> TokenStream {
impl_number(&info),
impl_serialize(&info),
impl_deserialize(&info),
impl_value(&info),
]);

TokenStream::from(expanded)
Expand Down
4 changes: 4 additions & 0 deletions tests/cases/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

* Add `Box<str>` and `&'static str` synonyms
* Add `NonZero*` synonyms
* Add `.value()` method
* Add `From<String>` for `Box<str>` synonyms
* Optimize `FromStr` for `Box<str>` synonyms
* Reorganize the documentation

## 0.1.3 (2024-06-05)

Expand Down
2 changes: 2 additions & 0 deletions tests/cases/pass-char.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ fn main() {
check_from(Foo('x'));
check_from_inner('x');
check_from_str(Foo('x'));
check_value(Foo('x').value());
}

fn check_partial_eq(_: impl PartialEq) {}
Expand All @@ -34,3 +35,4 @@ fn check_as_ref(_: impl AsRef<char>) {}
fn check_from(_: impl From<char>) {}
fn check_from_inner(_: impl From<Foo>) {}
fn check_from_str(_: impl core::str::FromStr) {}
fn check_value(_: char) {}
14 changes: 10 additions & 4 deletions tests/cases/pass-floats.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
use synonym::Synonym;

macro_rules! check {
($t:ty, $v:expr) => {
{
#[derive(Synonym)]
struct Foo($t);
mod dummy {
use synonym::Synonym;

#[derive(Synonym)]
pub struct Foo(pub $t);
}

use dummy::Foo;

fn check_as_ref(_: impl AsRef<$t>) {}
fn check_from(_: impl From<$t>) {}
fn check_from_inner(_: impl From<Foo>) {}
fn check_value(_: $t) {}

check_partial_eq(Foo($v));
check_partial_ord(Foo($v));
Expand All @@ -21,6 +26,7 @@ macro_rules! check {
check_from(Foo($v));
check_from_inner($v);
check_from_str(Foo($v));
check_value(Foo($v).value());
check_add(Foo($v));
check_sub(Foo($v));
check_mul(Foo($v));
Expand Down
Loading

0 comments on commit fb872ff

Please sign in to comment.