aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorBrian Anderson <[email protected]>2011-03-07 21:21:01 -0500
committerBrian Anderson <[email protected]>2011-03-07 21:21:01 -0500
commit9fc4db6b89213afdf45c02fc2bd2be62b0ddc40c (patch)
tree6c84574116273f91cbe89abd256b9f809adf97de /src/lib
parentAllow the else part of an expr_if to be either expr_if or expr_block (diff)
parentrustc: Cast the LLVM representations of tag types when constructing boxes. Un... (diff)
downloadrust-9fc4db6b89213afdf45c02fc2bd2be62b0ddc40c.tar.xz
rust-9fc4db6b89213afdf45c02fc2bd2be62b0ddc40c.zip
Merge branch 'master' into recursive-elseif
Conflicts: src/Makefile src/comp/front/ast.rs src/comp/front/parser.rs src/comp/middle/fold.rs src/comp/middle/trans.rs
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/_str.rs21
-rw-r--r--src/lib/io.rs (renamed from src/lib/_io.rs)57
-rw-r--r--src/lib/sha1.rs284
-rw-r--r--src/lib/std.rc5
4 files changed, 315 insertions, 52 deletions
diff --git a/src/lib/_str.rs b/src/lib/_str.rs
index 6b7ac018..0e0e7650 100644
--- a/src/lib/_str.rs
+++ b/src/lib/_str.rs
@@ -96,25 +96,10 @@ fn buf(str s) -> sbuf {
}
fn bytes(str s) -> vec[u8] {
- /* FIXME (issue #58):
- * Should be...
- *
- * fn ith(str s, uint i) -> u8 {
- * ret s.(i);
- * }
- * ret _vec.init_fn[u8](bind ith(s, _), byte_len(s));
- *
- * but we do not correctly decrement refcount of s when
- * the binding dies, so we have to do this manually.
- */
- let uint n = _str.byte_len(s);
- let vec[u8] v = _vec.alloc[u8](n);
- let uint i = 0u;
- while (i < n) {
- v += vec(s.(i));
- i += 1u;
+ fn ith(str s, uint i) -> u8 {
+ ret s.(i);
}
- ret v;
+ ret _vec.init_fn[u8](bind ith(s, _), byte_len(s));
}
fn from_bytes(vec[u8] v) : is_utf8(v) -> str {
diff --git a/src/lib/_io.rs b/src/lib/io.rs
index f285f6c8..0c4eb39e 100644
--- a/src/lib/_io.rs
+++ b/src/lib/io.rs
@@ -85,37 +85,34 @@ fn new_buf_reader(str path) -> buf_reader {
ret fd_buf_reader(fd, new_buf());
}
-/**
- * FIXME (issue #150): This should be
- *
- * type fileflag = tag(append(), create(), truncate());
- *
- * but then the tag value ctors are not found from crate-importers of std, so
- * we manually simulate the enum below.
- */
-type fileflag = uint;
-fn append() -> uint { ret 0u; }
-fn create() -> uint { ret 1u; }
-fn truncate() -> uint { ret 2u; }
+tag fileflag {
+ append;
+ create;
+ truncate;
+}
+
+fn writefd(int fd, vec[u8] v) {
+ auto len = _vec.len[u8](v);
+ auto count = 0u;
+ auto vbuf;
+ while (count < len) {
+ vbuf = _vec.buf_off[u8](v, count);
+ auto nout = os.libc.write(fd, vbuf, len);
+ if (nout < 0) {
+ log "error dumping buffer";
+ log sys.rustrt.last_os_error();
+ fail;
+ }
+ count += nout as uint;
+ }
+}
fn new_buf_writer(str path, vec[fileflag] flags) -> buf_writer {
state obj fd_buf_writer(int fd) {
fn write(vec[u8] v) {
- auto len = _vec.len[u8](v);
- auto count = 0u;
- auto vbuf;
- while (count < len) {
- vbuf = _vec.buf_off[u8](v, count);
- auto nout = os.libc.write(fd, vbuf, len);
- if (nout < 0) {
- log "error dumping buffer";
- log sys.rustrt.last_os_error();
- fail;
- }
- count += nout as uint;
- }
+ writefd(fd, v);
}
drop {
@@ -129,13 +126,9 @@ fn new_buf_writer(str path, vec[fileflag] flags) -> buf_writer {
for (fileflag f in flags) {
alt (f) {
- // FIXME (issue #150): cf comment above defn of fileflag type
- //case (append()) { fflags |= os.libc_constants.O_APPEND(); }
- //case (create()) { fflags |= os.libc_constants.O_CREAT(); }
- //case (truncate()) { fflags |= os.libc_constants.O_TRUNC(); }
- case (0u) { fflags |= os.libc_constants.O_APPEND(); }
- case (1u) { fflags |= os.libc_constants.O_CREAT(); }
- case (2u) { fflags |= os.libc_constants.O_TRUNC(); }
+ case (append) { fflags |= os.libc_constants.O_APPEND(); }
+ case (create) { fflags |= os.libc_constants.O_CREAT(); }
+ case (truncate) { fflags |= os.libc_constants.O_TRUNC(); }
}
}
diff --git a/src/lib/sha1.rs b/src/lib/sha1.rs
new file mode 100644
index 00000000..2a6b74d4
--- /dev/null
+++ b/src/lib/sha1.rs
@@ -0,0 +1,284 @@
+/*
+ * A SHA-1 implementation derived from Paul E. Jones's reference
+ * implementation, which is written for clarity, not speed. At some
+ * point this will want to be rewritten.
+ */
+
+import std._vec;
+import std._str;
+
+export sha1;
+export mk_sha1;
+
+state type sha1 = state obj {
+ // Provide message input as bytes
+ fn input(&vec[u8]);
+
+ // Provide message input as string
+ fn input_str(&str);
+
+ // Read the digest as a vector of 20 bytes. After
+ // calling this no further input may provided
+ // until reset is called
+ fn result() -> vec[u8];
+
+ // Reset the sha1 state for reuse. This is called
+ // automatically during construction
+ fn reset();
+};
+
+// Some unexported constants
+const uint digest_buf_len = 5;
+const uint msg_block_len = 64;
+
+// Builds a sha1 object
+fn mk_sha1() -> sha1 {
+
+ state type sha1state = rec(vec[mutable u32] h,
+ mutable u32 len_low,
+ mutable u32 len_high,
+ vec[mutable u8] msg_block,
+ mutable uint msg_block_idx,
+ mutable bool computed);
+
+ impure fn add_input(&sha1state st, &vec[u8] msg) {
+ // FIXME: Should be typestate precondition
+ check (!st.computed);
+
+ for (u8 element in msg) {
+ st.msg_block.(st.msg_block_idx) = element;
+ st.msg_block_idx += 1u;
+
+ st.len_low += 8u32;
+ if (st.len_low == 0u32) {
+ st.len_high += 1u32;
+ if (st.len_high == 0u32) {
+ // FIXME: Need better failure mode
+ fail;
+ }
+ }
+
+ if (st.msg_block_idx == msg_block_len) {
+ process_msg_block(st);
+ }
+ }
+ }
+
+ impure fn process_msg_block(&sha1state st) {
+
+ // FIXME: Make precondition
+ check (_vec.len[mutable u32](st.h) == digest_buf_len);
+
+ // Constants
+ auto k = vec(0x5A827999u32,
+ 0x6ED9EBA1u32,
+ 0x8F1BBCDCu32,
+ 0xCA62C1D6u32);
+
+ let int t; // Loop counter
+ let vec[mutable u32] w = _vec.init_elt[mutable u32](0u32, 80u);
+
+ // Initialize the first 16 words of the vector w
+ t = 0;
+ while (t < 16) {
+ w.(t) = (st.msg_block.(t * 4) as u32) << 24u32;
+ w.(t) = w.(t) | ((st.msg_block.(t * 4 + 1) as u32) << 16u32);
+ w.(t) = w.(t) | ((st.msg_block.(t * 4 + 2) as u32) << 8u32);
+ w.(t) = w.(t) | (st.msg_block.(t * 4 + 3) as u32);
+ t += 1;
+ }
+
+ // Initialize the rest of vector w
+ while (t < 80) {
+ auto val = w.(t-3) ^ w.(t-8) ^ w.(t-14) ^ w.(t-16);
+ w.(t) = circular_shift(1u32, val);
+ t += 1;
+ }
+
+ auto a = st.h.(0);
+ auto b = st.h.(1);
+ auto c = st.h.(2);
+ auto d = st.h.(3);
+ auto e = st.h.(4);
+
+ let u32 temp;
+
+ t = 0;
+ while (t < 20) {
+ temp = circular_shift(5u32, a)
+ + ((b & c) | ((~b) & d)) + e + w.(t) + k.(0);
+ e = d;
+ d = c;
+ c = circular_shift(30u32, b);
+ b = a;
+ a = temp;
+ t += 1;
+ }
+
+ while (t < 40) {
+ temp = circular_shift(5u32, a)
+ + (b ^ c ^ d) + e + w.(t) + k.(1);
+ e = d;
+ d = c;
+ c = circular_shift(30u32, b);
+ b = a;
+ a = temp;
+ t += 1;
+ }
+
+ while (t < 60) {
+ temp = circular_shift(5u32, a)
+ + ((b & c) | (b & d) | (c & d)) + e + w.(t) + k.(2);
+ e = d;
+ d = c;
+ c = circular_shift(30u32, b);
+ b = a;
+ a = temp;
+ t += 1;
+ }
+
+ while (t < 80) {
+ temp = circular_shift(5u32, a)
+ + (b ^ c ^ d) + e + w.(t) + k.(3);
+ e = d;
+ d = c;
+ c = circular_shift(30u32, b);
+ b = a;
+ a = temp;
+ t += 1;
+ }
+
+ st.h.(0) = st.h.(0) + a;
+ st.h.(1) = st.h.(1) + b;
+ st.h.(2) = st.h.(2) + c;
+ st.h.(3) = st.h.(3) + d;
+ st.h.(4) = st.h.(4) + e;
+
+ st.msg_block_idx = 0u;
+ }
+
+ fn circular_shift(u32 bits, u32 word) -> u32 {
+ // FIXME: This is a workaround for a rustboot
+ // "unrecognized quads" codegen bug
+ auto bits_hack = bits;
+ ret (word << bits_hack) | (word >> (32u32 - bits));
+ }
+
+ impure fn mk_result(&sha1state st) -> vec[u8] {
+ if (!st.computed) {
+ pad_msg(st);
+ st.computed = true;
+ }
+
+ let vec[u8] res = vec();
+ for (u32 hpart in st.h) {
+ res += (hpart >> 24u32) & 0xFFu32 as u8;
+ res += (hpart >> 16u32) & 0xFFu32 as u8;
+ res += (hpart >> 8u32) & 0xFFu32 as u8;
+ res += hpart & 0xFFu32 as u8;
+ }
+ ret res;
+ }
+
+ /*
+ * According to the standard, the message must be padded to an even
+ * 512 bits. The first padding bit must be a '1'. The last 64 bits
+ * represent the length of the original message. All bits in between
+ * should be 0. This function will pad the message according to those
+ * rules by filling the msg_block vector accordingly. It will also
+ * call process_msg_block() appropriately. When it returns, it
+ * can be assumed that the message digest has been computed.
+ */
+ impure fn pad_msg(&sha1state st) {
+ // FIXME: Should be a precondition
+ check (_vec.len[mutable u8](st.msg_block) == msg_block_len);
+
+ /*
+ * Check to see if the current message block is too small to hold
+ * the initial padding bits and length. If so, we will pad the
+ * block, process it, and then continue padding into a second block.
+ */
+ if (st.msg_block_idx > 55u) {
+ st.msg_block.(st.msg_block_idx) = 0x80u8;
+ st.msg_block_idx += 1u;
+
+ while (st.msg_block_idx < msg_block_len) {
+ st.msg_block.(st.msg_block_idx) = 0u8;
+ st.msg_block_idx += 1u;
+ }
+
+ process_msg_block(st);
+ } else {
+ st.msg_block.(st.msg_block_idx) = 0x80u8;
+ st.msg_block_idx += 1u;
+ }
+
+ while (st.msg_block_idx < 56u) {
+ st.msg_block.(st.msg_block_idx) = 0u8;
+ st.msg_block_idx += 1u;
+ }
+
+ // Store the message length as the last 8 octets
+ st.msg_block.(56) = (st.len_high >> 24u32) & 0xFFu32 as u8;
+ st.msg_block.(57) = (st.len_high >> 16u32) & 0xFFu32 as u8;
+ st.msg_block.(58) = (st.len_high >> 8u32) & 0xFFu32 as u8;
+ st.msg_block.(59) = st.len_high & 0xFFu32 as u8;
+ st.msg_block.(60) = (st.len_low >> 24u32) & 0xFFu32 as u8;
+ st.msg_block.(61) = (st.len_low >> 16u32) & 0xFFu32 as u8;
+ st.msg_block.(62) = (st.len_low >> 8u32) & 0xFFu32 as u8;
+ st.msg_block.(63) = st.len_low & 0xFFu32 as u8;
+
+ process_msg_block(st);
+ }
+
+ state obj sha1(sha1state st) {
+
+ fn reset() {
+ // FIXME: Should be typestate precondition
+ check (_vec.len[mutable u32](st.h) == digest_buf_len);
+
+ st.len_low = 0u32;
+ st.len_high = 0u32;
+ st.msg_block_idx = 0u;
+
+ st.h.(0) = 0x67452301u32;
+ st.h.(1) = 0xEFCDAB89u32;
+ st.h.(2) = 0x98BADCFEu32;
+ st.h.(3) = 0x10325476u32;
+ st.h.(4) = 0xC3D2E1F0u32;
+
+ st.computed = false;
+ }
+
+ fn input(&vec[u8] msg) {
+ add_input(st, msg);
+ }
+
+ fn input_str(&str msg) {
+ add_input(st, _str.bytes(msg));
+ }
+
+ fn result() -> vec[u8] {
+ ret mk_result(st);
+ }
+ }
+
+ auto st = rec(h = _vec.init_elt[mutable u32](0u32, digest_buf_len),
+ mutable len_low = 0u32,
+ mutable len_high = 0u32,
+ msg_block = _vec.init_elt[mutable u8](0u8, msg_block_len),
+ mutable msg_block_idx = 0u,
+ mutable computed = false);
+ auto sh = sha1(st);
+ sh.reset();
+ ret sh;
+}
+
+// Local Variables:
+// mode: rust;
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+// End:
diff --git a/src/lib/std.rc b/src/lib/std.rc
index 102aa4d1..4ad422a3 100644
--- a/src/lib/std.rc
+++ b/src/lib/std.rc
@@ -14,7 +14,7 @@ mod _str;
// General IO and system-services modules.
-mod _io;
+mod io;
mod sys;
mod _task;
@@ -25,7 +25,7 @@ mod util;
// Authorize various rule-bendings.
-auth _io = unsafe;
+auth io = unsafe;
auth _str = unsafe;
auth _vec = unsafe;
auth _task = unsafe;
@@ -57,6 +57,7 @@ mod dbg;
mod bitv;
mod sort;
mod path;
+mod sha1;
// Local Variables:
// mode: rust;