Skip to content

Commit

Permalink
case check option 1
Browse files Browse the repository at this point in the history
  • Loading branch information
sgeisler committed Jun 24, 2018
1 parent 4929ff4 commit 87dec05
Showing 1 changed file with 45 additions and 23 deletions.
68 changes: 45 additions & 23 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,41 @@ impl<T: AsRef<[u8]>> ToBase32<Vec<u5>> for T {
}
}

#[derive(Eq, PartialEq)]
enum Case {
None,
Upper,
Lower
}

struct CaseChecker {
last_case: Case,
}

impl CaseChecker {
#[inline]
pub fn check_case(&mut self, c: &char) -> Result<(), Error> {
if c.is_lowercase() {
if self.last_case == Case::Upper {
return Err(Error::MixedCase)
}
self.last_case = Case::Lower;
} else if c.is_uppercase() {
if self.last_case == Case::Lower {
return Err(Error::MixedCase)
}
self.last_case = Case::Upper;
}
Ok(())
}

pub fn new() -> CaseChecker {
CaseChecker {
last_case: Case::None
}
}
}

impl Bech32 {
/// Constructs a `Bech32` struct if the result can be encoded as a bech32 string.
pub fn new(hrp: String, data: Vec<u5>) -> Result<Bech32, Error> {
Expand Down Expand Up @@ -220,25 +255,21 @@ impl Bech32 {
return Err(Error::InvalidLength)
}

let mut has_lower: bool = false;
let mut has_upper: bool = false;
let mut case_checker = CaseChecker::new();
let mut hrp_bytes: Vec<u8> = Vec::new();
for b in raw_hrp.bytes() {
// Valid subset of ASCII
if b < 33 || b > 126 {
return Err(Error::InvalidChar(b as char))
}
let mut c = b;
// Lowercase
if b >= b'a' && b <= b'z' {
has_lower = true;
}
// Uppercase
if b >= b'A' && b <= b'Z' {
has_upper = true;
// Convert to lowercase
c = b + (b'a'-b'A');
}

case_checker.check_case(&(b as char))?;

let mut c = if b >= b'A' && b <= b'Z' {
b + (b'a'-b'A')
} else {
b
};
hrp_bytes.push(c);
}

Expand All @@ -250,11 +281,7 @@ impl Bech32 {
return Err(Error::InvalidChar(c))
}

if c.is_lowercase() {
has_lower = true;
} else if c.is_uppercase() {
has_upper = true;
}
case_checker.check_case(&c)?;

// c should be <128 since it is in the ASCII range, CHARSET_REV.len() == 128
let num_value = CHARSET_REV[c as usize];
Expand All @@ -266,11 +293,6 @@ impl Bech32 {
Ok(u5::try_from_u8(num_value as u8).expect("range checked above, num_value <= 31"))
}).collect::<Result<Vec<u5>, Error>>()?;

// Ensure no mixed case
if has_lower && has_upper {
return Err(Error::MixedCase)
}

// Ensure checksum
if !verify_checksum(&hrp_bytes, &data_bytes) {
return Err(Error::InvalidChecksum)
Expand Down

0 comments on commit 87dec05

Please sign in to comment.