From 428c58b9f983d31f9c7df2d48d45f6a22996692e Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 16 Nov 2012 15:12:14 -0800 Subject: [PATCH 01/11] Forbid duplicate supertraits I actually already pushed most of this by accident before I meant to, but r=nmatsakis anyway. Closes #3953 --- src/librustc/middle/typeck/collect.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 7fc0b65d10cae..0c6fe58576810 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -264,7 +264,7 @@ fn ensure_supertraits(ccx: @crate_ctxt, for trait_refs.each |trait_ref| { let (did, tpt) = instantiate_trait_ref(ccx, *trait_ref, rp); if instantiated.any(|other_trait: &InstantiatedTraitRef| - { (*other_trait).def_id == did }) { + { other_trait.def_id == did }) { // This means a trait inherited from the same supertrait more // than once. tcx.sess.span_err(sp, ~"Duplicate supertrait in trait \ From cacb085186106966a6f573cb95cc4a9b9ca90605 Mon Sep 17 00:00:00 2001 From: Jesse Jones Date: Sat, 17 Nov 2012 08:41:47 -0800 Subject: [PATCH 02/11] Made Map.contains_key, contains_key_ref, and get pure. --- src/libcore/mutable.rs | 2 +- src/libstd/map.rs | 18 +++++++++--------- src/libstd/smallintmap.rs | 8 ++++---- .../class-impl-very-parameterized-trait.rs | 6 +++--- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/libcore/mutable.rs b/src/libcore/mutable.rs index 56a6df2c4ddf1..eafdf58e67e9a 100644 --- a/src/libcore/mutable.rs +++ b/src/libcore/mutable.rs @@ -48,7 +48,7 @@ impl Data { } } - fn borrow_const(op: &fn(t: &const T) -> R) -> R { + pure fn borrow_const(op: &fn(t: &const T) -> R) -> R { op(&const self.value) } diff --git a/src/libstd/map.rs b/src/libstd/map.rs index 0ee7cb6fcf967..915202143a1ea 100644 --- a/src/libstd/map.rs +++ b/src/libstd/map.rs @@ -30,17 +30,17 @@ pub trait Map { fn insert(v: K, v: V) -> bool; /// Returns true if the map contains a value for the specified key - fn contains_key(key: K) -> bool; + pure fn contains_key(key: K) -> bool; /// Returns true if the map contains a value for the specified /// key, taking the key by reference. - fn contains_key_ref(key: &K) -> bool; + pure fn contains_key_ref(key: &K) -> bool; /** * Get the value for the specified key. Fails if the key does not exist in * the map. */ - fn get(key: K) -> V; + pure fn get(key: K) -> V; /** * Get the value for the specified key. If the key does not exist in @@ -200,11 +200,11 @@ pub mod chained { impl T: Map { pure fn size() -> uint { self.count } - fn contains_key(k: K) -> bool { + pure fn contains_key(k: K) -> bool { self.contains_key_ref(&k) } - fn contains_key_ref(k: &K) -> bool { + pure fn contains_key_ref(k: &K) -> bool { let hash = k.hash_keyed(0,0) as uint; match self.search_tbl(k, hash) { NotFound => false, @@ -264,7 +264,7 @@ pub mod chained { } } - fn get(k: K) -> V { + pure fn get(k: K) -> V { let opt_v = self.find(k); if opt_v.is_none() { fail fmt!("Key not found in table: %?", k); @@ -421,19 +421,19 @@ impl @Mut>: } } - fn contains_key(key: K) -> bool { + pure fn contains_key(key: K) -> bool { do self.borrow_const |p| { p.contains_key(&key) } } - fn contains_key_ref(key: &K) -> bool { + pure fn contains_key_ref(key: &K) -> bool { do self.borrow_const |p| { p.contains_key(key) } } - fn get(key: K) -> V { + pure fn get(key: K) -> V { do self.borrow_const |p| { p.get(&key) } diff --git a/src/libstd/smallintmap.rs b/src/libstd/smallintmap.rs index 1582d90ce2d62..9dc216a21557a 100644 --- a/src/libstd/smallintmap.rs +++ b/src/libstd/smallintmap.rs @@ -60,7 +60,7 @@ pub pure fn get(self: SmallIntMap, key: uint) -> T { } /// Returns true if the map contains a value for the specified key -pub fn contains_key(self: SmallIntMap, key: uint) -> bool { +pub pure fn contains_key(self: SmallIntMap, key: uint) -> bool { return !find(self, key).is_none(); } @@ -93,13 +93,13 @@ impl SmallIntMap: map::Map { fn clear() { self.v.set(~[]); } - fn contains_key(key: uint) -> bool { + pure fn contains_key(key: uint) -> bool { contains_key(self, key) } - fn contains_key_ref(key: &uint) -> bool { + pure fn contains_key_ref(key: &uint) -> bool { contains_key(self, *key) } - fn get(key: uint) -> V { get(self, key) } + pure fn get(key: uint) -> V { get(self, key) } pure fn find(key: uint) -> Option { find(self, key) } fn rehash() { fail } diff --git a/src/test/run-pass/class-impl-very-parameterized-trait.rs b/src/test/run-pass/class-impl-very-parameterized-trait.rs index 8c25d94db3bed..4cfcbf67cc9aa 100644 --- a/src/test/run-pass/class-impl-very-parameterized-trait.rs +++ b/src/test/run-pass/class-impl-very-parameterized-trait.rs @@ -47,10 +47,10 @@ impl cat : Map { self.meows += k; true } - fn contains_key(+k: int) -> bool { k <= self.meows } - fn contains_key_ref(k: &int) -> bool { self.contains_key(*k) } + pure fn contains_key(+k: int) -> bool { k <= self.meows } + pure fn contains_key_ref(k: &int) -> bool { self.contains_key(*k) } - fn get(+k:int) -> T { match self.find(k) { + pure fn get(+k:int) -> T { match self.find(k) { Some(v) => { v } None => { fail ~"epic fail"; } } From 67a5be9f5fa48ee129f37eadb39cd7f4a8b8ac33 Mon Sep 17 00:00:00 2001 From: Jesse Jones Date: Sat, 17 Nov 2012 09:11:57 -0800 Subject: [PATCH 03/11] Moved strptime and strftime into private helper functions. Makes the public API much easier to see and prepares the way for making them pure. --- src/libstd/time.rs | 160 ++++++++++++++++++++++++--------------------- 1 file changed, 84 insertions(+), 76 deletions(-) diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 75909273392f4..23ec6fef00300 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -152,6 +152,89 @@ pub fn now() -> Tm { /// Parses the time from the string according to the format string. pub fn strptime(s: &str, format: &str) -> Result { + do_strptime(s, format) +} + +pub fn strftime(format: &str, tm: Tm) -> ~str { + do_strftime(format, tm) +} + +impl Tm { + /// Convert time to the seconds from January 1, 1970 + fn to_timespec() -> Timespec { + let mut sec = 0i64; + if self.tm_gmtoff == 0_i32 { + rustrt::rust_timegm(self, &mut sec); + } else { + rustrt::rust_mktime(self, &mut sec); + } + { sec: sec, nsec: self.tm_nsec } + } + + /// Convert time to the local timezone + fn to_local() -> Tm { + at(self.to_timespec()) + } + + /// Convert time to the UTC + fn to_utc() -> Tm { + at_utc(self.to_timespec()) + } + + /** + * Return a string of the current time in the form + * "Thu Jan 1 00:00:00 1970". + */ + fn ctime() -> ~str { self.strftime(~"%c") } + + /// Formats the time according to the format string. + fn strftime(format: &str) -> ~str { strftime(format, self) } + + /** + * Returns a time string formatted according to RFC 822. + * + * local: "Thu, 22 Mar 2012 07:53:18 PST" + * utc: "Thu, 22 Mar 2012 14:53:18 UTC" + */ + fn rfc822() -> ~str { + if self.tm_gmtoff == 0_i32 { + self.strftime(~"%a, %d %b %Y %T GMT") + } else { + self.strftime(~"%a, %d %b %Y %T %Z") + } + } + + /** + * Returns a time string formatted according to RFC 822 with Zulu time. + * + * local: "Thu, 22 Mar 2012 07:53:18 -0700" + * utc: "Thu, 22 Mar 2012 14:53:18 -0000" + */ + fn rfc822z() -> ~str { + self.strftime(~"%a, %d %b %Y %T %z") + } + + /** + * Returns a time string formatted according to ISO 8601. + * + * local: "2012-02-22T07:53:18-07:00" + * utc: "2012-02-22T14:53:18Z" + */ + fn rfc3339() -> ~str { + if self.tm_gmtoff == 0_i32 { + self.strftime(~"%Y-%m-%dT%H:%M:%SZ") + } else { + let s = self.strftime(~"%Y-%m-%dT%H:%M:%S"); + let sign = if self.tm_gmtoff > 0_i32 { '+' } else { '-' }; + let mut m = i32::abs(self.tm_gmtoff) / 60_i32; + let h = m / 60_i32; + m -= h * 60_i32; + s + fmt!("%c%02d:%02d", sign, h as int, m as int) + } + } +} + +priv fn do_strptime(s: &str, format: &str) -> Result { type TmMut = { mut tm_sec: i32, mut tm_min: i32, @@ -592,7 +675,7 @@ pub fn strptime(s: &str, format: &str) -> Result { } } -fn strftime(format: &str, tm: Tm) -> ~str { +priv fn do_strftime(format: &str, tm: Tm) -> ~str { fn parse_type(ch: char, tm: &Tm) -> ~str { //FIXME (#2350): Implement missing types. let die = || fmt!("strftime: can't understand this format %c ", ch); @@ -759,81 +842,6 @@ fn strftime(format: &str, tm: Tm) -> ~str { buf } -impl Tm { - /// Convert time to the seconds from January 1, 1970 - fn to_timespec() -> Timespec { - let mut sec = 0i64; - if self.tm_gmtoff == 0_i32 { - rustrt::rust_timegm(self, &mut sec); - } else { - rustrt::rust_mktime(self, &mut sec); - } - { sec: sec, nsec: self.tm_nsec } - } - - /// Convert time to the local timezone - fn to_local() -> Tm { - at(self.to_timespec()) - } - - /// Convert time to the UTC - fn to_utc() -> Tm { - at_utc(self.to_timespec()) - } - - /** - * Return a string of the current time in the form - * "Thu Jan 1 00:00:00 1970". - */ - fn ctime() -> ~str { self.strftime(~"%c") } - - /// Formats the time according to the format string. - fn strftime(format: &str) -> ~str { strftime(format, self) } - - /** - * Returns a time string formatted according to RFC 822. - * - * local: "Thu, 22 Mar 2012 07:53:18 PST" - * utc: "Thu, 22 Mar 2012 14:53:18 UTC" - */ - fn rfc822() -> ~str { - if self.tm_gmtoff == 0_i32 { - self.strftime(~"%a, %d %b %Y %T GMT") - } else { - self.strftime(~"%a, %d %b %Y %T %Z") - } - } - - /** - * Returns a time string formatted according to RFC 822 with Zulu time. - * - * local: "Thu, 22 Mar 2012 07:53:18 -0700" - * utc: "Thu, 22 Mar 2012 14:53:18 -0000" - */ - fn rfc822z() -> ~str { - self.strftime(~"%a, %d %b %Y %T %z") - } - - /** - * Returns a time string formatted according to ISO 8601. - * - * local: "2012-02-22T07:53:18-07:00" - * utc: "2012-02-22T14:53:18Z" - */ - fn rfc3339() -> ~str { - if self.tm_gmtoff == 0_i32 { - self.strftime(~"%Y-%m-%dT%H:%M:%SZ") - } else { - let s = self.strftime(~"%Y-%m-%dT%H:%M:%S"); - let sign = if self.tm_gmtoff > 0_i32 { '+' } else { '-' }; - let mut m = i32::abs(self.tm_gmtoff) / 60_i32; - let h = m / 60_i32; - m -= h * 60_i32; - s + fmt!("%c%02d:%02d", sign, h as int, m as int) - } - } -} - #[cfg(test)] mod tests { #[legacy_exports]; From 2af7065d10ccf74c1ba53a1a9c2b29122ad34d2f Mon Sep 17 00:00:00 2001 From: Jesse Jones Date: Sat, 17 Nov 2012 09:17:43 -0800 Subject: [PATCH 04/11] Replace TmMut with inherited mutability --- src/libstd/time.rs | 46 ++++++++++++++++------------------------------ 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 23ec6fef00300..d5a5deeae8c08 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -155,6 +155,7 @@ pub fn strptime(s: &str, format: &str) -> Result { do_strptime(s, format) } +/// Formats the time according to the format string. pub fn strftime(format: &str, tm: Tm) -> ~str { do_strftime(format, tm) } @@ -235,21 +236,6 @@ impl Tm { } priv fn do_strptime(s: &str, format: &str) -> Result { - type TmMut = { - mut tm_sec: i32, - mut tm_min: i32, - mut tm_hour: i32, - mut tm_mday: i32, - mut tm_mon: i32, - mut tm_year: i32, - mut tm_wday: i32, - mut tm_yday: i32, - mut tm_isdst: i32, - mut tm_gmtoff: i32, - mut tm_zone: ~str, - mut tm_nsec: i32, - }; - fn match_str(s: &str, pos: uint, needle: &str) -> bool { let mut i = pos; for str::each(needle) |ch| { @@ -312,7 +298,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { } } - fn parse_type(s: &str, pos: uint, ch: char, tm: &TmMut) + fn parse_type(s: &str, pos: uint, ch: char, tm: &mut Tm_) -> Result { match ch { 'A' => match match_strs(s, pos, ~[ @@ -623,19 +609,19 @@ priv fn do_strptime(s: &str, format: &str) -> Result { } do io::with_str_reader(str::from_slice(format)) |rdr| { - let tm = { - mut tm_sec: 0_i32, - mut tm_min: 0_i32, - mut tm_hour: 0_i32, - mut tm_mday: 0_i32, - mut tm_mon: 0_i32, - mut tm_year: 0_i32, - mut tm_wday: 0_i32, - mut tm_yday: 0_i32, - mut tm_isdst: 0_i32, - mut tm_gmtoff: 0_i32, - mut tm_zone: ~"", - mut tm_nsec: 0_i32, + let mut tm = { + tm_sec: 0_i32, + tm_min: 0_i32, + tm_hour: 0_i32, + tm_mday: 0_i32, + tm_mon: 0_i32, + tm_year: 0_i32, + tm_wday: 0_i32, + tm_yday: 0_i32, + tm_isdst: 0_i32, + tm_gmtoff: 0_i32, + tm_zone: ~"", + tm_nsec: 0_i32, }; let mut pos = 0u; let len = str::len(s); @@ -645,7 +631,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { let {ch, next} = str::char_range_at(s, pos); match rdr.read_char() { - '%' => match parse_type(s, pos, rdr.read_char(), &tm) { + '%' => match parse_type(s, pos, rdr.read_char(), &mut tm) { Ok(next) => pos = next, Err(copy e) => { result = Err(e); break; } }, From 91d62991ab6dc4f38162fd1361a2b75af413f085 Mon Sep 17 00:00:00 2001 From: Jesse Jones Date: Sat, 17 Nov 2012 09:27:03 -0800 Subject: [PATCH 05/11] Made the time to string functions pure as well as empty_tm. This closes #3919. --- src/libstd/time.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/libstd/time.rs b/src/libstd/time.rs index d5a5deeae8c08..912df9c7558dd 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -107,7 +107,7 @@ impl Tm : Eq { pure fn ne(other: &Tm) -> bool { *self != *(*other) } } -pub fn empty_tm() -> Tm { +pub pure fn empty_tm() -> Tm { Tm_({ tm_sec: 0_i32, tm_min: 0_i32, @@ -151,13 +151,17 @@ pub fn now() -> Tm { } /// Parses the time from the string according to the format string. -pub fn strptime(s: &str, format: &str) -> Result { - do_strptime(s, format) +pub pure fn strptime(s: &str, format: &str) -> Result { + // unsafe only because do_strptime is annoying to make pure + // (it does IO with a str_reader) + unsafe {do_strptime(s, format)} } /// Formats the time according to the format string. -pub fn strftime(format: &str, tm: Tm) -> ~str { - do_strftime(format, tm) +pub pure fn strftime(format: &str, tm: Tm) -> ~str { + // unsafe only because do_strftime is annoying to make pure + // (it does IO with a str_reader) + unsafe {do_strftime(format, tm)} } impl Tm { @@ -186,10 +190,10 @@ impl Tm { * Return a string of the current time in the form * "Thu Jan 1 00:00:00 1970". */ - fn ctime() -> ~str { self.strftime(~"%c") } + pure fn ctime() -> ~str { self.strftime(~"%c") } /// Formats the time according to the format string. - fn strftime(format: &str) -> ~str { strftime(format, self) } + pure fn strftime(format: &str) -> ~str { strftime(format, self) } /** * Returns a time string formatted according to RFC 822. @@ -197,7 +201,7 @@ impl Tm { * local: "Thu, 22 Mar 2012 07:53:18 PST" * utc: "Thu, 22 Mar 2012 14:53:18 UTC" */ - fn rfc822() -> ~str { + pure fn rfc822() -> ~str { if self.tm_gmtoff == 0_i32 { self.strftime(~"%a, %d %b %Y %T GMT") } else { @@ -211,7 +215,7 @@ impl Tm { * local: "Thu, 22 Mar 2012 07:53:18 -0700" * utc: "Thu, 22 Mar 2012 14:53:18 -0000" */ - fn rfc822z() -> ~str { + pure fn rfc822z() -> ~str { self.strftime(~"%a, %d %b %Y %T %z") } @@ -221,7 +225,7 @@ impl Tm { * local: "2012-02-22T07:53:18-07:00" * utc: "2012-02-22T14:53:18Z" */ - fn rfc3339() -> ~str { + pure fn rfc3339() -> ~str { if self.tm_gmtoff == 0_i32 { self.strftime(~"%Y-%m-%dT%H:%M:%SZ") } else { From b4f802ebfe928280444b478ea0ce5582e13dc7df Mon Sep 17 00:00:00 2001 From: Jesse Jones Date: Sat, 17 Nov 2012 09:56:05 -0800 Subject: [PATCH 06/11] Made Result.get, get_ref, is_ok, is_err, and iter methods pure. Note that the function versions were already pure. --- src/libcore/result.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 2df2974d0ba31..da7db607c8559 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -204,13 +204,13 @@ pub fn map_err(res: &Result, op: fn((&E)) -> F) } impl Result { - fn get_ref(&self) -> &self/T { get_ref(self) } + pure fn get_ref(&self) -> &self/T { get_ref(self) } - fn is_ok() -> bool { is_ok(&self) } + pure fn is_ok() -> bool { is_ok(&self) } - fn is_err() -> bool { is_err(&self) } + pure fn is_err() -> bool { is_err(&self) } - fn iter(f: fn((&T))) { + pure fn iter(f: fn((&T))) { match self { Ok(ref t) => f(t), Err(_) => () @@ -226,7 +226,7 @@ impl Result { } impl Result { - fn get() -> T { get(&self) } + pure fn get() -> T { get(&self) } fn map_err(op: fn((&E)) -> F) -> Result { match self { @@ -237,7 +237,7 @@ impl Result { } impl Result { - fn get_err() -> E { get_err(&self) } + pure fn get_err() -> E { get_err(&self) } fn map(op: fn((&T)) -> U) -> Result { match self { From 772053134cb9ef0dda459394c5de8d45e597a0c5 Mon Sep 17 00:00:00 2001 From: Jesse Jones Date: Sat, 17 Nov 2012 09:57:14 -0800 Subject: [PATCH 07/11] Made most of the URL functions pure. This closes #3782. --- src/libstd/net_url.rs | 74 +++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/src/libstd/net_url.rs b/src/libstd/net_url.rs index 8ea9513d15518..dd76f65a046bc 100644 --- a/src/libstd/net_url.rs +++ b/src/libstd/net_url.rs @@ -27,7 +27,7 @@ type UserInfo = { pub type Query = ~[(~str, ~str)]; -pub fn Url(scheme: ~str, user: Option, host: ~str, +pub pure fn Url(scheme: ~str, user: Option, host: ~str, port: Option<~str>, path: ~str, query: Query, fragment: Option<~str>) -> Url { Url { scheme: move scheme, user: move user, host: move host, @@ -35,7 +35,7 @@ pub fn Url(scheme: ~str, user: Option, host: ~str, fragment: move fragment } } -fn UserInfo(user: ~str, pass: Option<~str>) -> UserInfo { +pure fn UserInfo(user: ~str, pass: Option<~str>) -> UserInfo { {user: move user, pass: move pass} } @@ -84,8 +84,9 @@ fn encode_inner(s: &str, full_url: bool) -> ~str { * * This function is compliant with RFC 3986. */ -pub fn encode(s: &str) -> ~str { - encode_inner(s, true) +pub pure fn encode(s: &str) -> ~str { + // unsafe only because encode_inner does (string) IO + unsafe {encode_inner(s, true)} } /** @@ -95,8 +96,9 @@ pub fn encode(s: &str) -> ~str { * This function is compliant with RFC 3986. */ -pub fn encode_component(s: &str) -> ~str { - encode_inner(s, false) +pub pure fn encode_component(s: &str) -> ~str { + // unsafe only because encode_inner does (string) IO + unsafe {encode_inner(s, false)} } fn decode_inner(s: &str, full_url: bool) -> ~str { @@ -142,15 +144,17 @@ fn decode_inner(s: &str, full_url: bool) -> ~str { * * This will only decode escape sequences generated by encode_uri. */ -pub fn decode(s: &str) -> ~str { - decode_inner(s, true) +pub pure fn decode(s: &str) -> ~str { + // unsafe only because decode_inner does (string) IO + unsafe {decode_inner(s, true)} } /** * Decode a string encoded with percent encoding. */ -pub fn decode_component(s: &str) -> ~str { - decode_inner(s, false) +pub pure fn decode_component(s: &str) -> ~str { + // unsafe only because decode_inner does (string) IO + unsafe {decode_inner(s, false)} } fn encode_plus(s: &str) -> ~str { @@ -264,19 +268,21 @@ pub fn decode_form_urlencoded(s: ~[u8]) -> } -fn split_char_first(s: &str, c: char) -> (~str, ~str) { +pure fn split_char_first(s: &str, c: char) -> (~str, ~str) { let len = str::len(s); let mut index = len; let mut mat = 0; - do io::with_str_reader(s) |rdr| { - let mut ch : char; - while !rdr.eof() { - ch = rdr.read_byte() as char; - if ch == c { - // found a match, adjust markers - index = rdr.tell()-1; - mat = 1; - break; + unsafe { + do io::with_str_reader(s) |rdr| { + let mut ch : char; + while !rdr.eof() { + ch = rdr.read_byte() as char; + if ch == c { + // found a match, adjust markers + index = rdr.tell()-1; + mat = 1; + break; + } } } } @@ -288,7 +294,7 @@ fn split_char_first(s: &str, c: char) -> (~str, ~str) { } } -fn userinfo_from_str(uinfo: &str) -> UserInfo { +pure fn userinfo_from_str(uinfo: &str) -> UserInfo { let (user, p) = split_char_first(uinfo, ':'); let pass = if str::len(p) == 0 { option::None @@ -315,12 +321,12 @@ impl UserInfo : Eq { pure fn ne(other: &UserInfo) -> bool { !self.eq(other) } } -fn query_from_str(rawquery: &str) -> Query { +pure fn query_from_str(rawquery: &str) -> Query { let mut query: Query = ~[]; if str::len(rawquery) != 0 { for str::split_char(rawquery, '&').each |p| { let (k, v) = split_char_first(*p, '='); - query.push((decode_component(k), decode_component(v))); + unsafe {query.push((decode_component(k), decode_component(v)));} }; } return query; @@ -340,7 +346,7 @@ pub pure fn query_to_str(query: Query) -> ~str { } // returns the scheme and the rest of the url, or a parsing error -pub fn get_scheme(rawurl: &str) -> result::Result<(~str, ~str), @~str> { +pub pure fn get_scheme(rawurl: &str) -> result::Result<(~str, ~str), @~str> { for str::each_chari(rawurl) |i,c| { match c { 'A' .. 'Z' | 'a' .. 'z' => loop, @@ -387,7 +393,7 @@ impl Input : Eq { } // returns userinfo, host, port, and unparsed part, or an error -fn get_authority(rawurl: &str) -> +pure fn get_authority(rawurl: &str) -> result::Result<(Option, ~str, Option<~str>, ~str), @~str> { if !str::starts_with(rawurl, ~"//") { // there is no authority. @@ -517,7 +523,7 @@ fn get_authority(rawurl: &str) -> let end = end; // make end immutable so it can be captured - let host_is_end_plus_one: &fn() -> bool = || { + let host_is_end_plus_one: &pure fn() -> bool = || { end+1 == len && !['?', '#', '/'].contains(&(rawurl[end] as char)) }; @@ -556,7 +562,7 @@ fn get_authority(rawurl: &str) -> // returns the path and unparsed part of url, or an error -fn get_path(rawurl: &str, authority : bool) -> +pure fn get_path(rawurl: &str, authority : bool) -> result::Result<(~str, ~str), @~str> { let len = str::len(rawurl); let mut end = len; @@ -587,7 +593,7 @@ fn get_path(rawurl: &str, authority : bool) -> } // returns the parsed query and the fragment, if present -fn get_query_fragment(rawurl: &str) -> +pure fn get_query_fragment(rawurl: &str) -> result::Result<(Query, Option<~str>), @~str> { if !str::starts_with(rawurl, ~"?") { if str::starts_with(rawurl, ~"#") { @@ -619,20 +625,20 @@ fn get_query_fragment(rawurl: &str) -> * */ -pub fn from_str(rawurl: &str) -> result::Result { +pub pure fn from_str(rawurl: &str) -> result::Result { // scheme let mut schm = get_scheme(rawurl); if result::is_err(&schm) { return result::Err(copy *result::get_err(&schm)); } - let (scheme, rest) = result::unwrap(schm); + let (scheme, rest) = schm.get(); // authority let mut auth = get_authority(rest); if result::is_err(&auth) { return result::Err(copy *result::get_err(&auth)); } - let (userinfo, host, port, rest) = result::unwrap(auth); + let (userinfo, host, port, rest) = auth.get(); // path let has_authority = if host == ~"" { false } else { true }; @@ -640,21 +646,21 @@ pub fn from_str(rawurl: &str) -> result::Result { if result::is_err(&pth) { return result::Err(copy *result::get_err(&pth)); } - let (path, rest) = result::unwrap(pth); + let (path, rest) = pth.get(); // query and fragment let mut qry = get_query_fragment(rest); if result::is_err(&qry) { return result::Err(copy *result::get_err(&qry)); } - let (query, fragment) = result::unwrap(qry); + let (query, fragment) = qry.get(); return result::Ok(Url(scheme, userinfo, host, port, path, query, fragment)); } impl Url : FromStr { - static fn from_str(s: &str) -> Option { + static pure fn from_str(s: &str) -> Option { match from_str(s) { Ok(move url) => Some(url), Err(_) => None From 2334158447a3e964d9c788cf7016f1f92a92d33a Mon Sep 17 00:00:00 2001 From: Jesse Jones Date: Sat, 17 Nov 2012 10:13:11 -0800 Subject: [PATCH 08/11] Made more stuff pure. escape functions in char, io.with_str_reader, base64 and md5sum, cell.empty_cell and is_empty. --- src/libcore/char.rs | 12 +-- src/libcore/io.rs | 2 +- src/libstd/base64.rs | 174 ++++++++++++++++++++++--------------------- src/libstd/cell.rs | 4 +- src/libstd/md4.rs | 14 ++-- 5 files changed, 105 insertions(+), 101 deletions(-) diff --git a/src/libcore/char.rs b/src/libcore/char.rs index b76571864e070..802aaf12bdd48 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -126,16 +126,18 @@ pub pure fn to_digit(c: char, radix: uint) -> Option { * - chars in [0x100,0xffff] get 4-digit escapes: `\\uNNNN` * - chars above 0x10000 get 8-digit escapes: `\\UNNNNNNNN` */ -pub fn escape_unicode(c: char) -> ~str { +pub pure fn escape_unicode(c: char) -> ~str { let s = u32::to_str(c as u32, 16u); let (c, pad) = (if c <= '\xff' { ('x', 2u) } else if c <= '\uffff' { ('u', 4u) } else { ('U', 8u) }); assert str::len(s) <= pad; let mut out = ~"\\"; - str::push_str(&mut out, str::from_char(c)); - for uint::range(str::len(s), pad) |_i| { str::push_str(&mut out, ~"0"); } - str::push_str(&mut out, s); + unsafe { + str::push_str(&mut out, str::from_char(c)); + for uint::range(str::len(s), pad) |_i| { str::push_str(&mut out, ~"0"); } + str::push_str(&mut out, s); + } move out } @@ -151,7 +153,7 @@ pub fn escape_unicode(c: char) -> ~str { * - Any other chars in the range [0x20,0x7e] are not escaped. * - Any other chars are given hex unicode escapes; see `escape_unicode`. */ -pub fn escape_default(c: char) -> ~str { +pub pure fn escape_default(c: char) -> ~str { match c { '\t' => ~"\\t", '\r' => ~"\\r", diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 4629878b4b7ea..535ab883581bb 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -512,7 +512,7 @@ pub pure fn with_bytes_reader(bytes: &[u8], f: fn(Reader) -> t) -> t { f(BytesReader { bytes: bytes, pos: 0u } as Reader) } -pub fn with_str_reader(s: &str, f: fn(Reader) -> T) -> T { +pub pure fn with_str_reader(s: &str, f: fn(Reader) -> T) -> T { str::byte_slice(s, |bytes| with_bytes_reader(bytes, f)) } diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs index 9bad4d3975003..177074de8f65a 100644 --- a/src/libstd/base64.rs +++ b/src/libstd/base64.rs @@ -2,72 +2,73 @@ use io::Reader; pub trait ToBase64 { - fn to_base64() -> ~str; + pure fn to_base64() -> ~str; } impl &[u8]: ToBase64 { - fn to_base64() -> ~str { + pure fn to_base64() -> ~str { let chars = str::chars( ~"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ); - let len = self.len(); let mut s = ~""; - str::reserve(&mut s, ((len + 3u) / 4u) * 3u); - - let mut i = 0u; - - while i < len - (len % 3u) { - let n = (self[i] as uint) << 16u | - (self[i + 1u] as uint) << 8u | - (self[i + 2u] as uint); - - // This 24-bit number gets separated into four 6-bit numbers. - str::push_char(&mut s, chars[(n >> 18u) & 63u]); - str::push_char(&mut s, chars[(n >> 12u) & 63u]); - str::push_char(&mut s, chars[(n >> 6u) & 63u]); - str::push_char(&mut s, chars[n & 63u]); - - i += 3u; - } - - // Heh, would be cool if we knew this was exhaustive - // (the dream of bounded integer types) - match len % 3 { - 0 => (), - 1 => { - let n = (self[i] as uint) << 16u; - str::push_char(&mut s, chars[(n >> 18u) & 63u]); - str::push_char(&mut s, chars[(n >> 12u) & 63u]); - str::push_char(&mut s, '='); - str::push_char(&mut s, '='); - } - 2 => { - let n = (self[i] as uint) << 16u | (self[i + 1u] as uint) << 8u; - str::push_char(&mut s, chars[(n >> 18u) & 63u]); - str::push_char(&mut s, chars[(n >> 12u) & 63u]); - str::push_char(&mut s, chars[(n >> 6u) & 63u]); - str::push_char(&mut s, '='); - } - _ => fail ~"Algebra is broken, please alert the math police" + unsafe { + let len = self.len(); + str::reserve(&mut s, ((len + 3u) / 4u) * 3u); + + let mut i = 0u; + + while i < len - (len % 3u) { + let n = (self[i] as uint) << 16u | + (self[i + 1u] as uint) << 8u | + (self[i + 2u] as uint); + + // This 24-bit number gets separated into four 6-bit numbers. + str::push_char(&mut s, chars[(n >> 18u) & 63u]); + str::push_char(&mut s, chars[(n >> 12u) & 63u]); + str::push_char(&mut s, chars[(n >> 6u) & 63u]); + str::push_char(&mut s, chars[n & 63u]); + + i += 3u; + } + + // Heh, would be cool if we knew this was exhaustive + // (the dream of bounded integer types) + match len % 3 { + 0 => (), + 1 => { + let n = (self[i] as uint) << 16u; + str::push_char(&mut s, chars[(n >> 18u) & 63u]); + str::push_char(&mut s, chars[(n >> 12u) & 63u]); + str::push_char(&mut s, '='); + str::push_char(&mut s, '='); + } + 2 => { + let n = (self[i] as uint) << 16u | (self[i + 1u] as uint) << 8u; + str::push_char(&mut s, chars[(n >> 18u) & 63u]); + str::push_char(&mut s, chars[(n >> 12u) & 63u]); + str::push_char(&mut s, chars[(n >> 6u) & 63u]); + str::push_char(&mut s, '='); + } + _ => fail ~"Algebra is broken, please alert the math police" + } } - s } } impl &str: ToBase64 { - fn to_base64() -> ~str { + pure fn to_base64() -> ~str { str::to_bytes(self).to_base64() } } pub trait FromBase64 { - fn from_base64() -> ~[u8]; + pure fn from_base64() -> ~[u8]; } impl ~[u8]: FromBase64 { - fn from_base64() -> ~[u8] { + pure fn from_base64() -> ~[u8] { if self.len() % 4u != 0u { fail ~"invalid base64 length"; } let len = self.len(); @@ -80,55 +81,56 @@ impl ~[u8]: FromBase64 { let mut r = vec::with_capacity((len / 4u) * 3u - padding); - let mut i = 0u; - while i < len { - let mut n = 0u; - - for iter::repeat(4u) { - let ch = self[i] as char; - n <<= 6u; - - if ch >= 'A' && ch <= 'Z' { - n |= (ch as uint) - 0x41u; - } else if ch >= 'a' && ch <= 'z' { - n |= (ch as uint) - 0x47u; - } else if ch >= '0' && ch <= '9' { - n |= (ch as uint) + 0x04u; - } else if ch == '+' { - n |= 0x3Eu; - } else if ch == '/' { - n |= 0x3Fu; - } else if ch == '=' { - match len - i { - 1u => { - r.push(((n >> 16u) & 0xFFu) as u8); - r.push(((n >> 8u ) & 0xFFu) as u8); - return copy r; - } - 2u => { - r.push(((n >> 10u) & 0xFFu) as u8); - return copy r; - } - _ => fail ~"invalid base64 padding" + unsafe { + let mut i = 0u; + while i < len { + let mut n = 0u; + + for iter::repeat(4u) { + let ch = self[i] as char; + n <<= 6u; + + if ch >= 'A' && ch <= 'Z' { + n |= (ch as uint) - 0x41u; + } else if ch >= 'a' && ch <= 'z' { + n |= (ch as uint) - 0x47u; + } else if ch >= '0' && ch <= '9' { + n |= (ch as uint) + 0x04u; + } else if ch == '+' { + n |= 0x3Eu; + } else if ch == '/' { + n |= 0x3Fu; + } else if ch == '=' { + match len - i { + 1u => { + r.push(((n >> 16u) & 0xFFu) as u8); + r.push(((n >> 8u ) & 0xFFu) as u8); + return copy r; + } + 2u => { + r.push(((n >> 10u) & 0xFFu) as u8); + return copy r; + } + _ => fail ~"invalid base64 padding" + } + } else { + fail ~"invalid base64 character"; } - } else { - fail ~"invalid base64 character"; - } - - i += 1u; - }; - - r.push(((n >> 16u) & 0xFFu) as u8); - r.push(((n >> 8u ) & 0xFFu) as u8); - r.push(((n ) & 0xFFu) as u8); + + i += 1u; + }; + + r.push(((n >> 16u) & 0xFFu) as u8); + r.push(((n >> 8u ) & 0xFFu) as u8); + r.push(((n ) & 0xFFu) as u8); + } } - r } } impl ~str: FromBase64 { - fn from_base64() -> ~[u8] { + pure fn from_base64() -> ~[u8] { str::to_bytes(self).from_base64() } } diff --git a/src/libstd/cell.rs b/src/libstd/cell.rs index 4f79bf2b31698..78027aa890760 100644 --- a/src/libstd/cell.rs +++ b/src/libstd/cell.rs @@ -12,7 +12,7 @@ pub fn Cell(value: T) -> Cell { Cell { value: Some(move value) } } -pub fn empty_cell() -> Cell { +pub pure fn empty_cell() -> Cell { Cell { value: None } } @@ -37,7 +37,7 @@ impl Cell { } /// Returns true if the cell is empty and false if the cell is full. - fn is_empty() -> bool { + pure fn is_empty() -> bool { self.value.is_none() } diff --git a/src/libstd/md4.rs b/src/libstd/md4.rs index 581beb78bdc55..d9bc03c311de7 100644 --- a/src/libstd/md4.rs +++ b/src/libstd/md4.rs @@ -1,6 +1,6 @@ #[forbid(deprecated_mode)]; -pub fn md4(msg: &[u8]) -> {a: u32, b: u32, c: u32, d: u32} { +pub pure fn md4(msg: &[u8]) -> {a: u32, b: u32, c: u32, d: u32} { // subtle: if orig_len is merely uint, then the code below // which performs shifts by 32 bits or more has undefined // results. @@ -10,14 +10,14 @@ pub fn md4(msg: &[u8]) -> {a: u32, b: u32, c: u32, d: u32} { let mut msg = vec::append(vec::from_slice(msg), ~[0x80u8]); let mut bitlen = orig_len + 8u64; while (bitlen + 64u64) % 512u64 > 0u64 { - msg.push(0u8); + unsafe {msg.push(0u8);} bitlen += 8u64; } // append length let mut i = 0u64; while i < 8u64 { - msg.push((orig_len >> (i * 8u64)) as u8); + unsafe {msg.push((orig_len >> (i * 8u64)) as u8);} i += 1u64; } @@ -26,7 +26,7 @@ pub fn md4(msg: &[u8]) -> {a: u32, b: u32, c: u32, d: u32} { let mut c = 0x98badcfeu32; let mut d = 0x10325476u32; - fn rot(r: int, x: u32) -> u32 { + pure fn rot(r: int, x: u32) -> u32 { let r = r as u32; (x << r) | (x >> (32u32 - r)) } @@ -84,9 +84,9 @@ pub fn md4(msg: &[u8]) -> {a: u32, b: u32, c: u32, d: u32} { return {a: a, b: b, c: c, d: d}; } -pub fn md4_str(msg: &[u8]) -> ~str { +pub pure fn md4_str(msg: &[u8]) -> ~str { let {a, b, c, d} = md4(msg); - fn app(a: u32, b: u32, c: u32, d: u32, f: fn(u32)) { + pure fn app(a: u32, b: u32, c: u32, d: u32, f: fn(u32)) { f(a); f(b); f(c); f(d); } let mut result = ~""; @@ -102,7 +102,7 @@ pub fn md4_str(msg: &[u8]) -> ~str { result } -pub fn md4_text(msg: &str) -> ~str { md4_str(str::to_bytes(msg)) } +pub pure fn md4_text(msg: &str) -> ~str { md4_str(str::to_bytes(msg)) } #[test] fn test_md4() { From 71d2cd9725eca6d78485e85fcfcb84d34b322afa Mon Sep 17 00:00:00 2001 From: Jesse Jones Date: Sat, 17 Nov 2012 10:21:14 -0800 Subject: [PATCH 09/11] Made merge_sort pure --- src/libstd/sort.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 4f06cc40c229c..451d5e805d051 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -13,10 +13,10 @@ type Le = pure fn(v1: &T, v2: &T) -> bool; * Has worst case O(n log n) performance, best case O(n), but * is not space efficient. This is a stable sort. */ -pub fn merge_sort(v: &[const T], le: Le) -> ~[T] { +pub pure fn merge_sort(v: &[const T], le: Le) -> ~[T] { type Slice = (uint, uint); - return merge_sort_(v, (0u, len(v)), le); + unsafe {return merge_sort_(v, (0u, len(v)), le);} fn merge_sort_(v: &[const T], slice: Slice, le: Le) -> ~[T] { From a4640cb21cd7fa0391fd2a03f4339ab8de2f2334 Mon Sep 17 00:00:00 2001 From: Jesse Jones Date: Sat, 17 Nov 2012 11:00:38 -0800 Subject: [PATCH 10/11] Fixing warnings for long and blank lines --- src/libcore/char.rs | 3 ++- src/libstd/base64.rs | 21 +++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 802aaf12bdd48..fb8cc274217d2 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -135,7 +135,8 @@ pub pure fn escape_unicode(c: char) -> ~str { let mut out = ~"\\"; unsafe { str::push_str(&mut out, str::from_char(c)); - for uint::range(str::len(s), pad) |_i| { str::push_str(&mut out, ~"0"); } + for uint::range(str::len(s), pad) |_i| + { str::push_str(&mut out, ~"0"); } str::push_str(&mut out, s); } move out diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs index 177074de8f65a..5db71b12185bc 100644 --- a/src/libstd/base64.rs +++ b/src/libstd/base64.rs @@ -15,23 +15,23 @@ impl &[u8]: ToBase64 { unsafe { let len = self.len(); str::reserve(&mut s, ((len + 3u) / 4u) * 3u); - + let mut i = 0u; - + while i < len - (len % 3u) { let n = (self[i] as uint) << 16u | (self[i + 1u] as uint) << 8u | (self[i + 2u] as uint); - + // This 24-bit number gets separated into four 6-bit numbers. str::push_char(&mut s, chars[(n >> 18u) & 63u]); str::push_char(&mut s, chars[(n >> 12u) & 63u]); str::push_char(&mut s, chars[(n >> 6u) & 63u]); str::push_char(&mut s, chars[n & 63u]); - + i += 3u; } - + // Heh, would be cool if we knew this was exhaustive // (the dream of bounded integer types) match len % 3 { @@ -44,7 +44,8 @@ impl &[u8]: ToBase64 { str::push_char(&mut s, '='); } 2 => { - let n = (self[i] as uint) << 16u | (self[i + 1u] as uint) << 8u; + let n = (self[i] as uint) << 16u | + (self[i + 1u] as uint) << 8u; str::push_char(&mut s, chars[(n >> 18u) & 63u]); str::push_char(&mut s, chars[(n >> 12u) & 63u]); str::push_char(&mut s, chars[(n >> 6u) & 63u]); @@ -85,11 +86,11 @@ impl ~[u8]: FromBase64 { let mut i = 0u; while i < len { let mut n = 0u; - + for iter::repeat(4u) { let ch = self[i] as char; n <<= 6u; - + if ch >= 'A' && ch <= 'Z' { n |= (ch as uint) - 0x41u; } else if ch >= 'a' && ch <= 'z' { @@ -116,10 +117,10 @@ impl ~[u8]: FromBase64 { } else { fail ~"invalid base64 character"; } - + i += 1u; }; - + r.push(((n >> 16u) & 0xFFu) as u8); r.push(((n >> 8u ) & 0xFFu) as u8); r.push(((n ) & 0xFFu) as u8); From a176242dc3ff0753ca1296a3c7ef67b94c709142 Mon Sep 17 00:00:00 2001 From: Jesse Jones Date: Sat, 17 Nov 2012 11:01:08 -0800 Subject: [PATCH 11/11] Made from_str pure --- src/libcore/from_str.rs | 2 +- src/libcore/int-template.rs | 9 ++++++--- src/libcore/uint-template.rs | 9 ++++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/libcore/from_str.rs b/src/libcore/from_str.rs index c4dd2536e2cfc..8e9cd5a022763 100644 --- a/src/libcore/from_str.rs +++ b/src/libcore/from_str.rs @@ -7,6 +7,6 @@ use option::Option; pub trait FromStr { - static fn from_str(s: &str) -> Option; + static pure fn from_str(s: &str) -> Option; } diff --git a/src/libcore/int-template.rs b/src/libcore/int-template.rs index db95bc46ffe8a..e5da7d6abe106 100644 --- a/src/libcore/int-template.rs +++ b/src/libcore/int-template.rs @@ -106,7 +106,7 @@ impl T: iter::Times { * * buf - A byte buffer * * radix - The base of the number */ -pub fn parse_bytes(buf: &[u8], radix: uint) -> Option { +pub pure fn parse_bytes(buf: &[u8], radix: uint) -> Option { if vec::len(buf) == 0u { return None; } let mut i = vec::len(buf) - 1u; let mut start = 0u; @@ -129,10 +129,13 @@ pub fn parse_bytes(buf: &[u8], radix: uint) -> Option { } /// Parse a string to an int -pub fn from_str(s: &str) -> Option { parse_bytes(str::to_bytes(s), 10u) } +pub pure fn from_str(s: &str) -> Option +{ + parse_bytes(str::to_bytes(s), 10u) +} impl T : FromStr { - static fn from_str(s: &str) -> Option { from_str(s) } + static pure fn from_str(s: &str) -> Option { from_str(s) } } /// Convert to a string in a given base diff --git a/src/libcore/uint-template.rs b/src/libcore/uint-template.rs index ceb525f5f8ddd..d406e36cc0771 100644 --- a/src/libcore/uint-template.rs +++ b/src/libcore/uint-template.rs @@ -100,7 +100,7 @@ impl T: iter::Times { * * `buf` must not be empty */ -pub fn parse_bytes(buf: &[const u8], radix: uint) -> Option { +pub pure fn parse_bytes(buf: &[const u8], radix: uint) -> Option { if vec::len(buf) == 0u { return None; } let mut i = vec::len(buf) - 1u; let mut power = 1u as T; @@ -117,10 +117,13 @@ pub fn parse_bytes(buf: &[const u8], radix: uint) -> Option { } /// Parse a string to an int -pub fn from_str(s: &str) -> Option { parse_bytes(str::to_bytes(s), 10u) } +pub pure fn from_str(s: &str) -> Option +{ + parse_bytes(str::to_bytes(s), 10u) +} impl T : FromStr { - static fn from_str(s: &str) -> Option { from_str(s) } + static pure fn from_str(s: &str) -> Option { from_str(s) } } /// Parse a string as an unsigned integer.