Skip to content

Commit 667c896

Browse files
committed
Add a Config struct following the builder pattern to idna
1 parent a1d8c88 commit 667c896

File tree

1 file changed

+86
-43
lines changed

1 file changed

+86
-43
lines changed

idna/src/uts46.rs

Lines changed: 86 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,90 @@ fn processing(domain: &str, flags: Flags, errors: &mut Vec<Error>) -> String {
353353
validated
354354
}
355355

356+
#[derive(Clone, Copy)]
357+
pub struct Config {
358+
flags: Flags,
359+
}
360+
361+
impl From<Flags> for Config {
362+
#[inline]
363+
fn from(flags: Flags) -> Self {
364+
Self { flags }
365+
}
366+
}
367+
368+
impl Config {
369+
#[inline]
370+
pub fn use_std3_ascii_rules(mut self, value: bool) -> Self {
371+
self.flags.use_std3_ascii_rules = value;
372+
self
373+
}
374+
375+
#[inline]
376+
pub fn transitional_processing(mut self, value: bool) -> Self {
377+
self.flags.transitional_processing = value;
378+
self
379+
}
380+
381+
#[inline]
382+
pub fn verify_dns_length(mut self, value: bool) -> Self {
383+
self.flags.verify_dns_length = value;
384+
self
385+
}
386+
387+
/// http://www.unicode.org/reports/tr46/#ToASCII
388+
pub fn to_ascii(self, domain: &str) -> Result<String, Errors> {
389+
let mut errors = Vec::new();
390+
let mut result = String::new();
391+
let mut first = true;
392+
for label in processing(domain, self.flags, &mut errors).split('.') {
393+
if !first {
394+
result.push('.');
395+
}
396+
first = false;
397+
if label.is_ascii() {
398+
result.push_str(label);
399+
} else {
400+
match punycode::encode_str(label) {
401+
Some(x) => {
402+
result.push_str(PUNYCODE_PREFIX);
403+
result.push_str(&x);
404+
},
405+
None => errors.push(Error::PunycodeError)
406+
}
407+
}
408+
}
409+
410+
if self.flags.verify_dns_length {
411+
let domain = if result.ends_with(".") { &result[..result.len()-1] } else { &*result };
412+
if domain.len() < 1 || domain.split('.').any(|label| label.len() < 1) {
413+
errors.push(Error::TooShortForDns)
414+
}
415+
if domain.len() > 253 || domain.split('.').any(|label| label.len() > 63) {
416+
errors.push(Error::TooLongForDns)
417+
}
418+
}
419+
if errors.is_empty() {
420+
Ok(result)
421+
} else {
422+
Err(Errors(errors))
423+
}
424+
}
425+
426+
/// http://www.unicode.org/reports/tr46/#ToUnicode
427+
pub fn to_unicode(self, domain: &str) -> (String, Result<(), Errors>) {
428+
let mut errors = Vec::new();
429+
let domain = processing(domain, self.flags, &mut errors);
430+
let errors = if errors.is_empty() {
431+
Ok(())
432+
} else {
433+
Err(Errors(errors))
434+
};
435+
(domain, errors)
436+
}
437+
438+
}
439+
356440
#[derive(Copy, Clone)]
357441
pub struct Flags {
358442
pub use_std3_ascii_rules: bool,
@@ -380,54 +464,13 @@ pub struct Errors(Vec<Error>);
380464

381465
/// http://www.unicode.org/reports/tr46/#ToASCII
382466
pub fn to_ascii(domain: &str, flags: Flags) -> Result<String, Errors> {
383-
let mut errors = Vec::new();
384-
let mut result = String::new();
385-
let mut first = true;
386-
for label in processing(domain, flags, &mut errors).split('.') {
387-
if !first {
388-
result.push('.');
389-
}
390-
first = false;
391-
if label.is_ascii() {
392-
result.push_str(label);
393-
} else {
394-
match punycode::encode_str(label) {
395-
Some(x) => {
396-
result.push_str(PUNYCODE_PREFIX);
397-
result.push_str(&x);
398-
},
399-
None => errors.push(Error::PunycodeError)
400-
}
401-
}
402-
}
403-
404-
if flags.verify_dns_length {
405-
let domain = if result.ends_with(".") { &result[..result.len()-1] } else { &*result };
406-
if domain.len() < 1 || domain.split('.').any(|label| label.len() < 1) {
407-
errors.push(Error::TooShortForDns)
408-
}
409-
if domain.len() > 253 || domain.split('.').any(|label| label.len() > 63) {
410-
errors.push(Error::TooLongForDns)
411-
}
412-
}
413-
if errors.is_empty() {
414-
Ok(result)
415-
} else {
416-
Err(Errors(errors))
417-
}
467+
Config::from(flags).to_ascii(domain)
418468
}
419469

420470
/// http://www.unicode.org/reports/tr46/#ToUnicode
421471
///
422472
/// Only `use_std3_ascii_rules` is used in `flags`.
423473
pub fn to_unicode(domain: &str, mut flags: Flags) -> (String, Result<(), Errors>) {
424474
flags.transitional_processing = false;
425-
let mut errors = Vec::new();
426-
let domain = processing(domain, flags, &mut errors);
427-
let errors = if errors.is_empty() {
428-
Ok(())
429-
} else {
430-
Err(Errors(errors))
431-
};
432-
(domain, errors)
475+
Config::from(flags).to_unicode(domain)
433476
}

0 commit comments

Comments
 (0)