Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

construct NamedFields from owned Strings #73

Closed
wants to merge 3 commits into from
Closed
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: 0 additions & 2 deletions tests/tests/field.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use valuable::NamedField;

fn assert_clone<T: Clone>() {}
fn assert_copy<T: Copy>() {}

#[test]
fn is_clone_copy() {
assert_clone::<NamedField<'static>>();
assert_copy::<NamedField<'static>>();
}
10 changes: 6 additions & 4 deletions valuable/src/enumerable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,10 +494,11 @@ impl Variant<'_> {
/// ```
/// use valuable::{Fields, NamedField, Variant, VariantDef};
///
/// static VARIANT: &VariantDef<'static> = &VariantDef::new(
/// "Foo", Fields::Named(&[NamedField::new("hello")]));
/// static NAMES: &[NamedField<'static>] = &[NamedField::new("hello")];
/// static VARIANT: VariantDef<'static> = VariantDef::new(
/// "Foo", Fields::Named(NAMES));
///
/// let variant = Variant::Static(VARIANT);
/// let variant = Variant::Static(&VARIANT);
/// assert!(variant.is_named_fields());
/// ```
///
Expand Down Expand Up @@ -525,8 +526,9 @@ impl Variant<'_> {
/// ```
/// use valuable::{Fields, NamedField, Variant, VariantDef};
///
/// static NAMES: &[NamedField<'static>] = &[NamedField::new("hello")];
/// static VARIANT: &VariantDef<'static> = &VariantDef::new(
/// "Foo", Fields::Named(&[NamedField::new("hello")]));
/// "Foo", Fields::Named(NAMES));
///
/// let variant = Variant::Static(VARIANT);
/// assert!(!variant.is_unnamed_fields());
Expand Down
66 changes: 62 additions & 4 deletions valuable/src/field.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#[cfg(all(feature = "alloc", not(valuable_no_atomic_cas)))]
use alloc::{string::String, sync::Arc};
use core::fmt;

/// Data stored within a `Structable` or an `Enumerable`.
#[derive(Debug)]
pub enum Fields<'a> {
Expand All @@ -9,8 +13,15 @@ pub enum Fields<'a> {
}

/// A named field
#[derive(Debug, Clone, Copy)]
pub struct NamedField<'a>(&'a str);
#[derive(Clone)]
pub struct NamedField<'a>(NamedFieldInner<'a>);

#[derive(Clone)]
enum NamedFieldInner<'a> {
Borrowed(&'a str),
#[cfg(all(feature = "alloc", not(valuable_no_atomic_cas)))]
Owned(Arc<str>),
}

impl Fields<'_> {
/// Returns `true` if the fields are named.
Expand Down Expand Up @@ -76,7 +87,24 @@ impl<'a> NamedField<'a> {
/// assert_eq!("hello", field.name());
/// ```
pub const fn new(name: &'a str) -> NamedField<'a> {
NamedField(name)
NamedField(NamedFieldInner::Borrowed(name))
}

/// Create a new `NamedField` instance from an owned [`String`].
///
/// # Examples
///
/// ```
/// use valuable::NamedField;
///
/// let what = "world";
/// let name = format!("hello_{}", what);
/// let field = NamedField::from_string(name);
/// assert_eq!("hello_world", field.name());
/// ```
#[cfg(all(feature = "alloc", not(valuable_no_atomic_cas)))]
pub fn from_string(name: String) -> NamedField<'static> {
NamedField(NamedFieldInner::Owned(Arc::from(name)))
}

/// Returns the field name
Expand All @@ -90,6 +118,36 @@ impl<'a> NamedField<'a> {
/// assert_eq!("hello", field.name());
/// ```
pub fn name(&self) -> &str {
self.0
match self.0 {
NamedFieldInner::Borrowed(name) => name,
#[cfg(all(feature = "alloc", not(valuable_no_atomic_cas)))]
NamedFieldInner::Owned(ref name) => name,
}
}
}

impl<'a> fmt::Debug for NamedField<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("NamedField").field(&self.name()).finish()
}
}

impl<'a> From<&'a str> for NamedField<'a> {
fn from(name: &'a str) -> Self {
Self::new(name)
}
}

#[cfg(all(feature = "alloc", not(valuable_no_atomic_cas)))]
impl From<String> for NamedField<'static> {
fn from(name: String) -> Self {
Self::from_string(name)
}
}

#[cfg(all(feature = "alloc", not(valuable_no_atomic_cas)))]
impl From<Arc<str>> for NamedField<'static> {
fn from(name: Arc<str>) -> Self {
Self(NamedFieldInner::Owned(name))
}
}
10 changes: 10 additions & 0 deletions valuable/src/structable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,16 @@ impl<'a> StructDef<'a> {
///
/// let def = StructDef::new_static("Foo", Fields::Unnamed);
/// ```
///
/// With named fields:
/// ```
/// use valuable::{StructDef, Fields, NamedField};
///
/// static NAMES: &[NamedField<'static>] = &[NamedField::new("hello")];
/// static MY_STRUCT: &StructDef<'static> = &StructDef::new_static(
/// "Foo",
/// Fields::Named(NAMES),
/// );
pub const fn new_static(name: &'static str, fields: Fields<'static>) -> StructDef<'a> {
StructDef::Static { name, fields }
}
Expand Down