diff --git a/Cargo.toml b/Cargo.toml index dab64399..c8693f01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "frunk" edition = "2021" -version = "0.4.2" +version = "0.4.3" authors = ["Lloyd "] description = "Frunk provides developers with a number of functional programming tools like HList, Coproduct, Generic, LabelledGeneric, Validated, Monoid, Semigroup and friends." license = "MIT" @@ -41,10 +41,15 @@ version = "0.5.0" serde = { version = "^1.0", optional = true, features = [ "derive" ] } [features] -default = ["validated", "proc-macros"] -validated = ["std"] +default = ["validated", "proc-macros", "alloc"] +validated = ["alloc"] proc-macros = ["frunk_proc_macros"] -std = ["frunk_core/std"] +std = ["alloc", "serde?/std"] +alloc = ["frunk_core/alloc", "serde?/alloc"] + +[[example]] +name = "paths" +required-features = ["proc-macros"] [profile.bench] opt-level = 3 diff --git a/core/Cargo.toml b/core/Cargo.toml index afc58b1b..35702935 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "frunk_core" edition = "2021" -version = "0.4.2" +version = "0.4.3" authors = ["Lloyd "] description = "Frunk core provides developers with HList, Coproduct, LabelledGeneric and Generic" license = "MIT" @@ -13,8 +13,11 @@ keywords = ["Frunk", "HList", "Generic", "Coproduct", "LabelledGeneric"] travis-ci = { repository = "lloydmeta/frunk" } [features] -default = ["std"] -std = [] +default = ["alloc"] +alloc = ["serde?/alloc"] + +# deprecated -- to be removed in next major version +std = ["alloc"] [dependencies] serde = { version = "^1.0", optional = true, features = [ "derive" ] } diff --git a/core/src/coproduct.rs b/core/src/coproduct.rs index 1582bd46..6bce74c4 100644 --- a/core/src/coproduct.rs +++ b/core/src/coproduct.rs @@ -1247,6 +1247,9 @@ mod tests { use super::Coproduct::*; use super::*; + use std::format; + use std::string::{String, ToString}; + #[test] fn test_coproduct_inject() { type I32StrBool = Coprod!(i32, &'static str, bool); @@ -1267,7 +1270,6 @@ mod tests { } #[test] - #[cfg(feature = "std")] fn test_coproduct_fold_consuming() { type I32F32StrBool = Coprod!(i32, f32, bool); @@ -1312,7 +1314,6 @@ mod tests { } #[test] - #[cfg(feature = "std")] fn test_coproduct_fold_non_consuming() { type I32F32Bool = Coprod!(i32, f32, bool); diff --git a/core/src/hlist.rs b/core/src/hlist.rs index 2fdee009..cb9d08f6 100644 --- a/core/src/hlist.rs +++ b/core/src/hlist.rs @@ -57,10 +57,12 @@ use crate::indices::{Here, Suffixed, There}; use crate::traits::{Func, IntoReverse, Poly, ToMut, ToRef}; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use std::ops::Add; +use core::ops::Add; /// Typeclass for HList-y behaviour /// @@ -432,7 +434,7 @@ macro_rules! gen_inherent_methods { /// # } /// ``` #[inline(always)] - pub fn map(self,mapper: F) -> >::Output + pub fn map(self, mapper: F) -> >::Output where Self: HMappable, { HMappable::map(self, mapper) @@ -1433,7 +1435,7 @@ where } } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[allow(clippy::from_over_into)] impl Into> for HCons where @@ -1450,7 +1452,7 @@ where } } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[allow(clippy::from_over_into)] impl Into> for HNil { fn into(self) -> Vec { @@ -1577,6 +1579,8 @@ where mod tests { use super::*; + use alloc::vec; + #[test] fn test_hcons() { let hlist1 = h_cons(1, HNil); @@ -1909,7 +1913,6 @@ mod tests { } #[test] - #[cfg(feature = "std")] fn test_single_func_foldl_consuming() { use std::collections::HashMap; @@ -1949,7 +1952,7 @@ mod tests { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn test_into_vec() { let h = hlist![1, 2, 3, 4, 5]; let as_vec: Vec<_> = h.into(); diff --git a/core/src/indices.rs b/core/src/indices.rs index 69419665..440bcd7a 100644 --- a/core/src/indices.rs +++ b/core/src/indices.rs @@ -11,7 +11,7 @@ //! //! **...yet.** `;)` -use std::marker::PhantomData; +use core::marker::PhantomData; // Largely lifted from https://github.com/Sgeo/hlist/blob/master/src/lib.rs#L30 diff --git a/core/src/labelled.rs b/core/src/labelled.rs index fbbf6a28..2e5162d9 100644 --- a/core/src/labelled.rs +++ b/core/src/labelled.rs @@ -152,8 +152,8 @@ use crate::indices::*; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use ::std::fmt; -use ::std::marker::PhantomData; +use core::fmt; +use core::marker::PhantomData; /// A trait that converts from a type to a labelled generic representation. /// @@ -733,11 +733,13 @@ impl Transmogrifier for Field { @@ -914,7 +916,8 @@ where mod tests { use super::chars::*; use super::*; - use ::std::collections::{LinkedList, VecDeque}; + use alloc::collections::{LinkedList, VecDeque}; + use alloc::{boxed::Box, format, vec, vec::Vec}; // Set up some aliases #[allow(non_camel_case_types)] diff --git a/core/src/lib.rs b/core/src/lib.rs index bc16035f..51c6148e 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,4 +1,4 @@ -#![cfg_attr(not(feature = "std"), no_std)] +#![no_std] #![doc(html_playground_url = "https://play.rust-lang.org/")] //! Frunk Core //! @@ -58,8 +58,11 @@ //! 1. [Source on Github](https://github.com/lloydmeta/frunk) //! 2. [Crates.io page](https://crates.io/crates/frunk) -#[cfg(not(feature = "std"))] -extern crate core as std; +#[cfg(test)] +extern crate std; + +#[cfg(feature = "alloc")] +extern crate alloc; #[macro_use] mod macros; diff --git a/core/src/path.rs b/core/src/path.rs index 800a77f9..93c5f226 100644 --- a/core/src/path.rs +++ b/core/src/path.rs @@ -108,8 +108,8 @@ use super::hlist::*; use super::labelled::*; -use std::marker::PhantomData; -use std::ops::Add; +use core::marker::PhantomData; +use core::ops::Add; #[derive(Clone, Copy, Debug)] pub struct Path(PhantomData); diff --git a/laws/Cargo.toml b/laws/Cargo.toml index 576948b6..a2a75b32 100644 --- a/laws/Cargo.toml +++ b/laws/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "frunk_laws" edition = "2021" -version = "0.5.0" +version = "0.5.1" authors = ["Lloyd "] description = "frunk_laws contains laws for algebras declared in Frunk." license = "MIT" @@ -16,6 +16,7 @@ travis-ci = { repository = "lloydmeta/frunk" } path = ".." default-features = false version = "0.4.2" +features = ["std"] [dependencies] quickcheck = "1.0.3" diff --git a/laws/src/monoid_laws.rs b/laws/src/monoid_laws.rs index ed0d5671..fe33bf9a 100644 --- a/laws/src/monoid_laws.rs +++ b/laws/src/monoid_laws.rs @@ -66,39 +66,33 @@ mod tests { use crate::wrapper::*; use frunk::semigroup::*; use quickcheck::quickcheck; - #[cfg(feature = "std")] use std::collections::{HashMap, HashSet}; #[test] - #[cfg(feature = "std")] fn string_id_prop() { quickcheck(left_identity as fn(String) -> bool); quickcheck(right_identity as fn(String) -> bool); } #[test] - #[cfg(feature = "std")] fn option_id_prop() { quickcheck(left_identity as fn(Option) -> bool); quickcheck(right_identity as fn(Option) -> bool); } #[test] - #[cfg(feature = "std")] fn vec_id_prop() { quickcheck(left_identity as fn(Vec) -> bool); quickcheck(right_identity as fn(Vec) -> bool); } #[test] - #[cfg(feature = "std")] fn hashset_id_prop() { quickcheck(left_identity as fn(HashSet) -> bool); quickcheck(right_identity as fn(HashSet) -> bool); } #[test] - #[cfg(feature = "std")] fn hashmap_id_prop() { quickcheck(left_identity as fn(HashMap) -> bool); quickcheck(right_identity as fn(HashMap) -> bool); diff --git a/laws/src/semigroup_laws.rs b/laws/src/semigroup_laws.rs index 10f5c6de..dd8577dd 100644 --- a/laws/src/semigroup_laws.rs +++ b/laws/src/semigroup_laws.rs @@ -42,35 +42,29 @@ mod tests { use super::*; use crate::wrapper::*; use quickcheck::quickcheck; - #[cfg(feature = "std")] use std::collections::{HashMap, HashSet}; #[test] - #[cfg(feature = "std")] fn string_prop() { quickcheck(associativity as fn(String, String, String) -> bool) } #[test] - #[cfg(feature = "std")] fn option_prop() { quickcheck(associativity as fn(Option, Option, Option) -> bool) } #[test] - #[cfg(feature = "std")] fn vec_prop() { quickcheck(associativity as fn(Vec, Vec, Vec) -> bool) } #[test] - #[cfg(feature = "std")] fn hashset_prop() { quickcheck(associativity as fn(HashSet, HashSet, HashSet) -> bool) } #[test] - #[cfg(feature = "std")] fn hashmap_prop() { quickcheck( associativity diff --git a/src/lib.rs b/src/lib.rs index 79afb525..2633c15a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![cfg_attr(not(feature = "std"), no_std)] +#![no_std] #![doc(html_playground_url = "https://play.rust-lang.org/")] //! Frunk: generic functional programming toolbelt for Rust //! @@ -13,7 +13,7 @@ //! 6. Monoid //! #![cfg_attr( - feature = "std", + feature = "alloc", doc = r#" Here is a small taste of what Frunk has to offer: @@ -201,8 +201,11 @@ assert_eq!(d_user.first_name, "Joe"); //! 1. [Source on Github](https://github.com/lloydmeta/frunk) //! 2. [Crates.io page](https://crates.io/crates/frunk) -#[cfg(not(feature = "std"))] -extern crate core as std; +#[cfg(feature = "alloc")] +extern crate alloc; + +#[cfg(any(feature = "std", test))] +extern crate std; pub mod monoid; pub mod semigroup; diff --git a/src/monoid.rs b/src/monoid.rs index bea302fd..9c2130e6 100644 --- a/src/monoid.rs +++ b/src/monoid.rs @@ -11,7 +11,8 @@ their values are summed in the new map? # Examples ``` -use std::collections::HashMap; +# extern crate std; +# use std::collections::HashMap; use frunk::{monoid, Monoid}; let vec_of_no_hashmaps: Vec> = Vec::new(); @@ -37,10 +38,12 @@ assert_eq!(monoid::combine_all(&vec_of_hashes), h_expected); )] use super::semigroup::{All, Any, Product, Semigroup}; +#[cfg(feature = "alloc")] +use alloc::{string::String, vec::Vec}; #[cfg(feature = "std")] -use std::collections::*; +use core::hash::Hash; #[cfg(feature = "std")] -use std::hash::Hash; +use std::collections::*; /// A Monoid is a Semigroup that has an empty/ zero value pub trait Monoid: Semigroup { @@ -78,11 +81,14 @@ where /// Given a sequence of `xs`, combine them and return the total #[cfg_attr( - feature = "std", + feature = "alloc", doc = r#" # Examples ``` +# extern crate alloc; +# use alloc::vec::Vec; +# use alloc::string::String; use frunk::monoid::combine_all; assert_eq!(combine_all(&vec![Some(1), Some(3)]), Some(4)); @@ -111,14 +117,14 @@ where } } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Monoid for String { fn empty() -> Self { String::new() } } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Monoid for Vec where T: Clone, @@ -292,6 +298,9 @@ mod tests { use super::super::semigroup::{All, Any, Product}; use super::*; + #[cfg(feature = "alloc")] + use alloc::{borrow::ToOwned, vec}; + #[test] fn test_combine_n() { assert_eq!(combine_n(&1, 0), 0); @@ -301,7 +310,7 @@ mod tests { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn test_combine_all_basic() { assert_eq!(combine_all(&[1, 2, 3]), 6); assert_eq!(combine_all(&[] as &[i32]), 0); @@ -383,7 +392,7 @@ mod tests { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn test_combine_all_tuple() { let t1 = (1, 2.5f32, String::from("hi"), Some(3)); let t2 = (1, 2.5f32, String::from(" world"), None); diff --git a/src/semigroup.rs b/src/semigroup.rs index 515759d3..3ed1ec5e 100644 --- a/src/semigroup.rs +++ b/src/semigroup.rs @@ -2,7 +2,7 @@ //! //! You can, for example, combine tuples. #![cfg_attr( - feature = "std", + feature = "alloc", doc = r#" # Examples @@ -29,16 +29,18 @@ assert_eq!(h1.combine(&h2), h3) ```"# )] +#[cfg(feature = "alloc")] +use alloc::{boxed::Box, string::String, vec::Vec}; +use core::cell::*; +use core::cmp::Ordering; +#[cfg(feature = "alloc")] +use core::hash::Hash; +use core::ops::{BitAnd, BitOr, Deref}; use frunk_core::hlist::*; -use std::cell::*; -use std::cmp::Ordering; #[cfg(feature = "std")] use std::collections::hash_map::Entry; #[cfg(feature = "std")] use std::collections::{HashMap, HashSet}; -#[cfg(feature = "std")] -use std::hash::Hash; -use std::ops::{BitAnd, BitOr, Deref}; /// Wrapper type for types that are ordered and can have a Max combination #[derive(PartialEq, Debug, Eq, Clone, Copy, PartialOrd, Ord, Hash)] @@ -168,14 +170,14 @@ where } } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Semigroup for Box { fn combine(&self, other: &Self) -> Self { Box::new(self.deref().combine(other.deref())) } } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Semigroup for String { fn combine(&self, other: &Self) -> Self { let mut cloned = self.clone(); @@ -184,7 +186,7 @@ impl Semigroup for String { } } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Semigroup for Vec { fn combine(&self, other: &Self) -> Self { let mut v = self.clone(); @@ -361,6 +363,9 @@ tuple_impls! { #[cfg(test)] mod tests { use super::*; + #[cfg(feature = "alloc")] + use alloc::{borrow::ToOwned, vec}; + #[cfg(feature = "alloc")] use frunk_core::hlist; macro_rules! semigroup_tests { @@ -393,7 +398,7 @@ mod tests { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn test_string() { let v1 = String::from("Hello"); let v2 = String::from(" world"); @@ -401,7 +406,7 @@ mod tests { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn test_vec_i32() { let v1 = vec![1, 2, 3]; let v2 = vec![4, 5, 6]; @@ -506,7 +511,7 @@ mod tests { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn test_combine_hlist() { let h1 = hlist![Some(1), 3.3, 53i64, "hello".to_owned()]; let h2 = hlist![Some(2), 1.2, 1i64, " world".to_owned()]; diff --git a/src/validated.rs b/src/validated.rs index 351cd6e6..ea33156f 100644 --- a/src/validated.rs +++ b/src/validated.rs @@ -46,7 +46,8 @@ use super::hlist::*; -use std::ops::Add; +use alloc::{vec, vec::Vec}; +use core::ops::Add; /// A Validated is either an Ok holding an HList or an Err, holding a vector /// of collected errors. @@ -244,6 +245,7 @@ where #[cfg(test)] mod tests { use super::*; + use alloc::{borrow::ToOwned, string::String}; use frunk_core::{hlist, hlist_pat}; #[test]