Skip to content

Commit

Permalink
alloc feature added for unicode_normalization
Browse files Browse the repository at this point in the history
This commit introduces the `alloc` feature. It is enabled by default by `std`.

The alloc is intended to use in no-std environments which are allowed to
use alloc. New feature enables:

- the unicode-normalization, and all related methods (parse_in,normalize_utf8_cow,parse,to_seed)
- to_entropy() method as Vec is available in alloc,

Some formatting sneaked in, too.
  • Loading branch information
michalkucharczyk committed Nov 13, 2023
1 parent a7649ae commit 1372108
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 31 deletions.
23 changes: 12 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ edition = "2018"

[features]
default = [ "std" ]
std = [ "unicode-normalization", "serde/std" ]
std = [ "serde/std", "unicode-normalization/std" ]
rand = [ "crate_rand", "rand_core" ]
alloc = [ "unicode-normalization" ]

# Note: English is the standard for bip39 so always included
chinese-simplified = []
Expand All @@ -28,15 +29,15 @@ portuguese = []
spanish = []

all-languages = [
"chinese-simplified",
"chinese-traditional",
"czech",
"french",
"italian",
"japanese",
"korean",
"portuguese",
"spanish"
"chinese-simplified",
"chinese-traditional",
"czech",
"french",
"italian",
"japanese",
"korean",
"portuguese",
"spanish",
]

[dependencies]
Expand All @@ -49,7 +50,7 @@ zeroize = { version = "1.5", features = ["zeroize_derive"], optional = true }

# Unexported dependnecies
bitcoin_hashes = { version = "0.11.0", default-features = false }
unicode-normalization = { version = "=0.1.22", optional = true }
unicode-normalization = { version = "=0.1.22", default-features=false, optional = true }

[dev-dependencies]
# Enabling the "rand" feature by default to run the benches
Expand Down
34 changes: 14 additions & 20 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,26 +33,25 @@ extern crate alloc;

extern crate bitcoin_hashes;

#[cfg(feature = "std")]
#[cfg(any(feature = "alloc", feature = "std"))]
extern crate unicode_normalization;

#[cfg(feature = "rand_core")]
pub extern crate rand_core;
#[cfg(feature = "rand")]
pub extern crate crate_rand as rand;
#[cfg(feature = "rand_core")]
pub extern crate rand_core;
#[cfg(feature = "serde")]
pub extern crate serde;

use alloc::{borrow::Cow, string::ToString, vec::Vec};
use core::{fmt, str};

#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(feature = "std")]
use std::error;

use bitcoin_hashes::{sha256, Hash};

#[cfg(feature = "std")]
#[cfg(any(feature = "alloc", feature = "std"))]
use unicode_normalization::UnicodeNormalization;

#[cfg(feature = "zeroize")]
Expand Down Expand Up @@ -95,7 +94,7 @@ impl AmbiguousLanguages {
}

/// Returns a vector of the possible languages.
#[cfg(feature = "std")]
#[cfg(any(feature = "alloc", feature = "std"))]
pub fn to_vec(&self) -> Vec<Language> {
self.iter().collect()
}
Expand Down Expand Up @@ -183,7 +182,7 @@ impl Mnemonic {
/// Performing this on a [Cow] means that all allocations for normalization
/// can be avoided for languages without special UTF8 characters.
#[inline]
#[cfg(feature = "std")]
#[cfg(any(feature = "alloc", feature = "std"))]
pub fn normalize_utf8_cow<'a>(cow: &mut Cow<'a, str>) {
let is_nfkd = unicode_normalization::is_nfkd_quick(cow.as_ref().chars());
if is_nfkd != unicode_normalization::IsNormalized::Yes {
Expand Down Expand Up @@ -506,7 +505,7 @@ impl Mnemonic {
}

/// Parse a mnemonic in the given language.
#[cfg(feature = "std")]
#[cfg(any(feature = "alloc", feature = "std"))]
pub fn parse_in<'a, S: Into<Cow<'a, str>>>(
language: Language,
s: S,
Expand All @@ -517,7 +516,7 @@ impl Mnemonic {
}

/// Parse a mnemonic and detect the language from the enabled languages.
#[cfg(feature = "std")]
#[cfg(any(feature = "alloc", feature = "std"))]
pub fn parse<'a, S: Into<Cow<'a, str>>>(s: S) -> Result<Mnemonic, Error> {
let mut cow = s.into();
Mnemonic::normalize_utf8_cow(&mut cow);
Expand All @@ -542,17 +541,12 @@ impl Mnemonic {
const PBKDF2_BYTES: usize = 64;

let mut seed = [0u8; PBKDF2_BYTES];
pbkdf2::pbkdf2(
self.words(),
normalized_passphrase.as_bytes(),
PBKDF2_ROUNDS,
&mut seed,
);
pbkdf2::pbkdf2(self.words(), normalized_passphrase.as_bytes(), PBKDF2_ROUNDS, &mut seed);
seed
}

/// Convert to seed bytes.
#[cfg(feature = "std")]
#[cfg(any(feature = "alloc", feature = "std"))]
pub fn to_seed<'a, P: Into<Cow<'a, str>>>(&self, passphrase: P) -> [u8; 64] {
let normalized_passphrase = {
let mut cow = passphrase.into();
Expand Down Expand Up @@ -601,7 +595,7 @@ impl Mnemonic {
}

/// Convert the mnemonic back to the entropy used to generate it.
#[cfg(feature = "std")]
#[cfg(any(feature = "alloc", feature = "std"))]
pub fn to_entropy(&self) -> Vec<u8> {
let (arr, len) = self.to_entropy_array();
arr[0..len].to_vec()
Expand All @@ -624,11 +618,11 @@ impl str::FromStr for Mnemonic {
type Err = Error;

fn from_str(s: &str) -> Result<Mnemonic, Error> {
#[cfg(feature = "std")]
#[cfg(any(feature = "alloc", feature = "std"))]
{
Mnemonic::parse(s)
}
#[cfg(not(feature = "std"))]
#[cfg(all(not(feature = "alloc"), not(feature = "std")))]
{
Mnemonic::parse_normalized(s)
}
Expand Down

0 comments on commit 1372108

Please sign in to comment.