Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "polymorphic-constant"
version = "0.2.0"
version = "0.2.1"
edition = "2018"

authors = ["Louis Garczynski <louis.roc@gmail.com>"]
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ A few features are supported:
/// Doc comment attributes
const PI: f32 | f64 = 3.141592653589793;

// Visibility modifiers (for both constant and type)
// Visibility modifiers (constant, type and fields)
pub (crate) const E: f32 | f64 = 2.7182818284590452;

// Nonzero numeric types (NonZeroI32, NonZeroU8, etc)
Expand Down
45 changes: 21 additions & 24 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ A few features are supported:
/// Doc comment attributes
const PI: f32 | f64 = 3.141592653589793;

// Visibility modifiers (for both constant and type)
// Visibility modifiers (constant, type and fields)
pub (crate) const E: f32 | f64 = 2.7182818284590452;

// Nonzero numeric types (NonZeroI32, NonZeroU8, etc)
Expand Down Expand Up @@ -110,6 +110,20 @@ Any incompatible type will prevent compilation:
# }
```

* A constant and its fields are never more visible than declared
```compile_fail
# use polymorphic_constant::polymorphic_constant;

mod inner {
# use polymorphic_constant::polymorphic_constant;
polymorphic_constant! {
const HIDDEN: i32 = 1;
}
}

let fails = inner::HIDDEN.i32;
```

* However, floats may lose precision, and a lot of it
```rust
# use polymorphic_constant::polymorphic_constant;
Expand Down Expand Up @@ -193,8 +207,8 @@ let x_i32 = X.i32;

#[macro_export(local_inner_macros)]
macro_rules! polymorphic_constant {
// Handle the const (pub?) CONST format
($(#[$attr:meta])* ($($vis:tt)*) const $name:ident : $( $numeric_type:ident )|* = $lit:literal; $($nextLine:tt)*) => {
// Handle the (pub?) const CONST format
($(#[$attr:meta])* $vis:vis const $name:ident : $( $numeric_type:ident )|* = $lit:literal; $($nextLine:tt)*) => {

// Generate the struct to hold the constant

Expand All @@ -204,12 +218,10 @@ macro_rules! polymorphic_constant {
#[cfg_attr(not(no_std), derive(Debug, Clone, Copy))]
// Expend the attributes passed by the user
$(#[$attr])*
// Add the visibility attributes
$($vis)*
// Create the struct
struct $name {
// For each type (f32, ...) create a new property
$($numeric_type: __nz_impl!(@GET_TYPE $numeric_type),)*
$vis struct $name {
// Without $vis, `X.f32` is unreadable outside the defining module
$($vis $numeric_type: __nz_impl!(@GET_TYPE $numeric_type),)*
}

// Implement `into` for every type
Expand All @@ -219,29 +231,14 @@ macro_rules! polymorphic_constant {
}
})*

// Expand the visibility, this time for the constant
$($vis)*
// Instantiate the struct and create the constant
const $name: $name = $name {
$vis const $name: $name = $name {
$($numeric_type: __nz_impl!(@MAKE_VAL $lit, $numeric_type ),)*
};
// Keep munching until the next ;
polymorphic_constant!($($nextLine)*);
};

// Handle `const CONST` format
($(#[$attr:meta])* const $($t:tt)*) => {
// use `()` to explicitly forward the information about private items
polymorphic_constant!($(#[$attr])* () const $($t)*);
};
// Handle `pub const CONST` format
($(#[$attr:meta])* pub const $($t:tt)*) => {
polymorphic_constant!($(#[$attr])* (pub) const $($t)*);
};
// Handle `pub (crate) CONST` format and similar
($(#[$attr:meta])* pub ($($vis:tt)+) const $($t:tt)*) => {
polymorphic_constant!($(#[$attr])* (pub ($($vis)+)) const $($t)*);
};
() => {};
}

Expand Down
32 changes: 32 additions & 0 deletions tests/tests-visibility.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#![no_std]
#![cfg(test)]

mod inner {
use polymorphic_constant::polymorphic_constant;

polymorphic_constant! {
pub const PUBLIC: i16 | i32 = 10;
pub (crate) const CRATE: i16 | i32 = 20;
pub (in crate::inner) const RESTRICTED: i16 | i32 = 30;
const PRIVATE: i16 | i32 = 40;
}

pub fn private_is_reachable_here() -> i32 {
PRIVATE.i32 + RESTRICTED.i32
}
}

use inner::{CRATE, PUBLIC};

#[test]
fn fields_follow_constant_visibility() {
assert_eq!(PUBLIC.i16, 10);
assert_eq!(PUBLIC.i32, 10);
assert_eq!(CRATE.i16, 20);
assert_eq!(CRATE.i32, 20);
}

#[test]
fn private_stays_module_local() {
assert_eq!(inner::private_is_reachable_here(), 70);
}
Loading