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: 2 additions & 0 deletions .rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
hard_tabs = true
use_small_heuristics = "Off"
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CHANGELOG
=========


# v1.0.0

- Initial version of entire rewrite.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "bip39"
version = "1.0.0-rc1"
version = "1.0.0"
authors = ["Steven Roose <steven@stevenroose.org>"]
license = "CC0-1.0"
homepage = "https://github.com/rust-bitcoin/rust-bip39/"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ Use the `all-languages` feature to enable all languages.

## MSRV

This crate supports Rust v1.29 and up.
This crate supports Rust v1.29 and up and works with `no_std`.

43 changes: 24 additions & 19 deletions benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ use test::Bencher;
use bip39::*;

#[cfg(not(any(
feature = "chinese-simplified", feature = "chinese-traditional", feature = "czech",
feature = "french", feature = "italian", feature = "japanese", feature = "korean",
feature = "chinese-simplified",
feature = "chinese-traditional",
feature = "czech",
feature = "french",
feature = "italian",
feature = "japanese",
feature = "korean",
feature = "spanish"
)))]
const LANG: Language = Language::English;
Expand All @@ -32,38 +37,38 @@ const LANG: Language = Language::Spanish;

#[bench]
fn validate(b: &mut Bencher) {
let entropy = "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f".as_bytes();
let mnemonic = Mnemonic::from_entropy_in(LANG, &entropy).unwrap();
let entropy = "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f".as_bytes();
let mnemonic = Mnemonic::from_entropy_in(LANG, &entropy).unwrap();
assert_eq!(mnemonic.word_count(), 24);
let phrase = mnemonic.to_string();

b.iter(|| {
let _ = Mnemonic::parse_in(Language::English, &phrase);
});
b.iter(|| {
let _ = Mnemonic::parse_in(Language::English, &phrase);
});
}

#[bench]
fn from_entropy(b: &mut Bencher) {
let entropy = "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f".as_bytes();
let entropy = "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f".as_bytes();

b.iter(|| {
let _ = Mnemonic::from_entropy_in(LANG, &entropy).unwrap();
});
b.iter(|| {
let _ = Mnemonic::from_entropy_in(LANG, &entropy).unwrap();
});
}

#[bench]
fn new_mnemonic(b: &mut Bencher) {
b.iter(|| {
let _ = Mnemonic::generate_in(LANG, 24);
});
b.iter(|| {
let _ = Mnemonic::generate_in(LANG, 24);
});
}

#[bench]
fn to_seed(b: &mut Bencher) {
let entropy = "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f".as_bytes();
let m = Mnemonic::from_entropy_in(LANG, &entropy).unwrap();
let entropy = "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f".as_bytes();
let m = Mnemonic::from_entropy_in(LANG, &entropy).unwrap();

b.iter(|| {
let _ = m.to_seed("");
});
b.iter(|| {
let _ = m.to_seed("");
});
}
109 changes: 54 additions & 55 deletions src/internal_macros.rs
Original file line number Diff line number Diff line change
@@ -1,59 +1,58 @@

/// Implement serde serialization based on the
/// fmt::Display and std::FromStr traits.
macro_rules! serde_string_impl {
($name:ident, $expecting:expr) => {
#[cfg(feature = "serde")]
impl<'de> $crate::serde::Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> Result<$name, D::Error>
where
D: $crate::serde::de::Deserializer<'de>,
{
use ::std::fmt::{self, Formatter};
use ::std::str::FromStr;

struct Visitor;
impl<'de> $crate::serde::de::Visitor<'de> for Visitor {
type Value = $name;

fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str($expecting)
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: $crate::serde::de::Error,
{
$name::from_str(v).map_err(E::custom)
}

fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
where
E: $crate::serde::de::Error,
{
self.visit_str(v)
}

fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: $crate::serde::de::Error,
{
self.visit_str(&v)
}
}

deserializer.deserialize_str(Visitor)
}
}

#[cfg(feature = "serde")]
impl<'de> $crate::serde::Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: $crate::serde::Serializer,
{
serializer.collect_str(&self)
}
}
};
($name:ident, $expecting:expr) => {
#[cfg(feature = "serde")]
impl<'de> $crate::serde::Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> Result<$name, D::Error>
where
D: $crate::serde::de::Deserializer<'de>,
{
use std::fmt::{self, Formatter};
use std::str::FromStr;

struct Visitor;
impl<'de> $crate::serde::de::Visitor<'de> for Visitor {
type Value = $name;

fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str($expecting)
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: $crate::serde::de::Error,
{
$name::from_str(v).map_err(E::custom)
}

fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
where
E: $crate::serde::de::Error,
{
self.visit_str(v)
}

fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: $crate::serde::de::Error,
{
self.visit_str(&v)
}
}

deserializer.deserialize_str(Visitor)
}
}

#[cfg(feature = "serde")]
impl<'de> $crate::serde::Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: $crate::serde::Serializer,
{
serializer.collect_str(&self)
}
}
};
}
47 changes: 34 additions & 13 deletions src/language/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@

use core::fmt;

mod english;
#[cfg(feature = "chinese-simplified")]
mod chinese_simplified;
#[cfg(feature = "chinese-traditional")]
mod chinese_traditional;
#[cfg(feature = "czech")]
mod czech;
mod english;
#[cfg(feature = "french")]
mod french;
#[cfg(feature = "italian")]
Expand Down Expand Up @@ -142,7 +141,7 @@ impl Language {
None => return &[],
};
let count = self.word_list()[first..].iter().take_while(|w| w.starts_with(prefix)).count();
&self.word_list()[first .. first + count]
&self.word_list()[first..first + count]
}

/// Get the index of the word in the word list.
Expand All @@ -163,8 +162,13 @@ mod tests {
use super::*;

#[cfg(all(
feature = "chinese-simplified", feature = "chinese-traditional", feature = "czech",
feature = "french", feature = "italian", feature = "japanese", feature = "korean",
feature = "chinese-simplified",
feature = "chinese-traditional",
feature = "czech",
feature = "french",
feature = "italian",
feature = "japanese",
feature = "korean",
feature = "spanish"
))]
#[test]
Expand All @@ -185,13 +189,22 @@ mod tests {
use bitcoin_hashes::{sha256, Hash, HashEngine};

let checksums = [
("5c5942792bd8340cb8b27cd592f1015edf56a8c5b26276ee18a482428e7c5726", Language::SimplifiedChinese),
("417b26b3d8500a4ae3d59717d7011952db6fc2fb84b807f3f94ac734e89c1b5f", Language::TraditionalChinese),
(
"5c5942792bd8340cb8b27cd592f1015edf56a8c5b26276ee18a482428e7c5726",
Language::SimplifiedChinese,
),
(
"417b26b3d8500a4ae3d59717d7011952db6fc2fb84b807f3f94ac734e89c1b5f",
Language::TraditionalChinese,
),
("7e80e161c3e93d9554c2efb78d4e3cebf8fc727e9c52e03b83b94406bdcc95fc", Language::Czech),
("2f5eed53a4727b4bf8880d8f3f199efc90e58503646d9ff8eff3a2ed3b24dbda", Language::English),
("ebc3959ab7801a1df6bac4fa7d970652f1df76b683cd2f4003c941c63d517e59", Language::French),
("d392c49fdb700a24cd1fceb237c1f65dcc128f6b34a8aacb58b59384b5c648c2", Language::Italian),
("2eed0aef492291e061633d7ad8117f1a2b03eb80a29d0e4e3117ac2528d05ffd", Language::Japanese),
(
"2eed0aef492291e061633d7ad8117f1a2b03eb80a29d0e4e3117ac2528d05ffd",
Language::Japanese,
),
("9e95f86c167de88f450f0aaf89e87f6624a57f973c67b516e338e8e8b8897f60", Language::Korean),
("46846a5a0139d1e3cb77293e521c2865f7bcdb82c44e8d0a06a2cd0ecba48c0b", Language::Spanish),
];
Expand All @@ -206,8 +219,11 @@ mod tests {
digest.input("\n".as_bytes());
}
#[cfg(feature = "std")]
assert_eq!(sha256::Hash::from_engine(digest).to_string(), _sum,
"word list for language {} failed checksum check", lang,
assert_eq!(
sha256::Hash::from_engine(digest).to_string(),
_sum,
"word list for language {} failed checksum check",
lang,
);
}
}
Expand All @@ -217,7 +233,7 @@ mod tests {
let lang = Language::English;

let res = lang.words_by_prefix("woo");
assert_eq!(res, ["wood","wool"]);
assert_eq!(res, ["wood", "wool"]);

let res = lang.words_by_prefix("");
assert_eq!(res.len(), 2048);
Expand All @@ -227,8 +243,13 @@ mod tests {
}

#[cfg(all(
feature = "chinese-simplified", feature = "chinese-traditional", feature = "czech",
feature = "french", feature = "italian", feature = "japanese", feature = "korean",
feature = "chinese-simplified",
feature = "chinese-traditional",
feature = "czech",
feature = "french",
feature = "italian",
feature = "japanese",
feature = "korean",
feature = "spanish"
))]
#[test]
Expand Down
Loading