nandi/rustnimpublic Fork 0
af6e50f646055dc5b291c9e602bc9ee01874f9d6
Commits
Clone
git clone https://git.rickub.com/nandi/rustnim.git
git clone ssh://git@rickub.com/nandi/rustnim.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Transpile a second crate, adler2, to test whether any of this generalises 5fdd5be · on af6e50f646055dc5b291c9e602bc9ee01874f9d6 · nandithebull · 17h ago
main.rs · 148 lines · 3.8 KBRust Blame HistoryRaw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//@ args: run
// adler2 2.0.1. `algo.rs` is the crate's own file, byte-for-byte.
// This root carries `lib.rs`'s items (its `BufRead` reader needs std I/O
// and is left out) plus a driver, since the runner needs a `main`.

mod algo;

use core::hash::Hasher;

#[derive(Debug, Copy, Clone)]
pub struct Adler32 {
    a: u16,
    b: u16,
}

impl Adler32 {
    /// Creates a new Adler-32 instance with default state.
    #[inline]
    pub fn new() -> Self {
        Self::default()
    }

    /// Creates an `Adler32` instance from a precomputed Adler-32 checksum.
    ///
    /// This allows resuming checksum calculation without having to keep the `Adler32` instance
    /// around.
    ///
    /// # Example
    ///
    /// ```
    /// # use adler2::Adler32;
    /// let parts = [
    ///     "rust",
    ///     "acean",
    /// ];
    /// let whole = adler2::adler32_slice(b"rustacean");
    ///
    /// let mut sum = Adler32::new();
    /// sum.write_slice(parts[0].as_bytes());
    /// let partial = sum.checksum();
    ///
    /// // ...later
    ///
    /// let mut sum = Adler32::from_checksum(partial);
    /// sum.write_slice(parts[1].as_bytes());
    /// assert_eq!(sum.checksum(), whole);
    /// ```
    #[inline]
    pub const fn from_checksum(sum: u32) -> Self {
        Adler32 {
            a: sum as u16,
            b: (sum >> 16) as u16,
        }
    }

    /// Returns the calculated checksum at this point in time.
    #[inline]
    pub fn checksum(&self) -> u32 {
        (u32::from(self.b) << 16) | u32::from(self.a)
    }

    /// Adds `bytes` to the checksum calculation.
    ///
    /// If efficiency matters, this should be called with Byte slices that contain at least a few
    /// thousand Bytes.
    pub fn write_slice(&mut self, bytes: &[u8]) {
        self.compute(bytes);
    }
}

impl Default for Adler32 {
    #[inline]
    fn default() -> Self {
        Adler32 { a: 1, b: 0 }
    }
}

impl Hasher for Adler32 {
    #[inline]
    fn finish(&self) -> u64 {
        u64::from(self.checksum())
    }

    fn write(&mut self, bytes: &[u8]) {
        self.write_slice(bytes);
    }
}

/// Calculates the Adler-32 checksum of a byte slice.
///
/// This is a convenience function around the [`Adler32`] type.
///
/// [`Adler32`]: struct.Adler32.html
pub fn adler32_slice(data: &[u8]) -> u32 {
    let mut h = Adler32::new();
    h.write_slice(data);
    h.checksum()
}

fn main() {
    // Known vectors: the empty input, "Wikipedia", and simple patterns.
    println!("{:08x}", adler32_slice(b""));
    println!("{:08x}", adler32_slice(b"Wikipedia"));
    println!("{:08x}", adler32_slice(b"a"));
    println!("{:08x}", adler32_slice(b"abc"));

    // Every single byte.
    let mut i: u32 = 0;
    while i < 256 {
        let one: [u8; 1] = [i as u8];
        print!("{:08x} ", adler32_slice(&one));
        i += 1;
    }
    println!("");

    // Lengths across the 4-byte unrolling boundary and well past it, so the
    // chunked path, the remainder path and the serial tail are all exercised.
    let mut n: usize = 0;
    while n <= 600 {
        let mut buf: Vec<u8> = vec![0u8; n];
        let mut j: usize = 0;
        while j < n {
            buf[j] = ((j * 31 + 7) % 256) as u8;
            j += 1;
        }
        print!("{:08x} ", adler32_slice(&buf));
        n += 1;
    }
    println!("");

    // Incremental writes must equal one write of the concatenation.
    let mut data: Vec<u8> = vec![0u8; 1000];
    let mut k: usize = 0;
    while k < 1000 {
        data[k] = ((k * 97 + 13) % 256) as u8;
        k += 1;
    }
    let mut split: usize = 0;
    while split <= 1000 {
        let mut h = Adler32::new();
        h.write_slice(&data[..split]);
        h.write_slice(&data[split..]);
        print!("{:08x} ", h.checksum());
        split += 7;
    }
    println!("");
    println!("{:08x}", adler32_slice(&data));
}