1
use std::collections::HashMap;
2
use std::io::Read;
3

            
4
use merc_utilities::MercError;
5

            
6
use crate::Ldd;
7
use crate::Storage;
8
use crate::Value;
9

            
10
/// A reader for LDDs in the Sylvan .ldd format.
11
pub struct SylvanReader {
12
    indexed_set: HashMap<u64, Ldd>, // Assigns LDDs to every index.
13
    last_index: u64,                // The index of the last LDD read from file.
14
}
15

            
16
impl SylvanReader {
17
3
    pub fn new() -> Self {
18
3
        Self {
19
3
            indexed_set: HashMap::new(),
20
3
            last_index: 2,
21
3
        }
22
3
    }
23

            
24
    /// Returns an LDD read from the given stream in the Sylvan format.
25
25
    pub fn read_ldd(&mut self, storage: &mut Storage, stream: &mut impl Read) -> Result<Ldd, MercError> {
26
25
        let count = read_u64(stream)?;
27
        //println!("node count = {}", count);
28

            
29
25
        for _ in 0..count {
30
            // Read a single MDD node. It has the following structure: u64 | u64
31
            // RmRR RRRR RRRR VVVV | VVVV DcDD DDDD DDDD (little endian)
32
            // Every character is 4 bits, V = value, D = down, R = right, m = marked, c = copy.
33
205
            let a = read_u64(stream)?;
34
205
            let b = read_u64(stream)?;
35
            //println!("{:064b} | {:064b}", a, b);
36

            
37
205
            let right = (a & 0x0000ffffffffffff) >> 1;
38
205
            let down = b >> 17;
39

            
40
205
            let mut bytes: [u8; 4] = Default::default();
41
205
            bytes[0..2].copy_from_slice(&a.to_le_bytes()[6..8]);
42
205
            bytes[2..4].copy_from_slice(&b.to_le_bytes()[0..2]);
43
205
            let value = u32::from_le_bytes(bytes);
44

            
45
205
            let copy = right & 0x10000;
46
205
            if copy != 0 {
47
                panic!("We do not yet deal with copy nodes.");
48
205
            }
49

            
50
205
            let down = self.node_from_index(storage, down);
51
205
            let right = self.node_from_index(storage, right);
52

            
53
205
            let ldd = storage.insert(value as Value, &down, &right);
54
205
            self.indexed_set.insert(self.last_index, ldd);
55

            
56
205
            self.last_index += 1;
57
        }
58

            
59
25
        let result = read_u64(stream)?;
60
25
        Ok(self.node_from_index(storage, result))
61
25
    }
62

            
63
    /// Returns the LDD belonging to the given index.
64
1305
    fn node_from_index(&self, storage: &mut Storage, index: u64) -> Ldd {
65
1305
        if index == 0 {
66
492
            storage.empty_set().clone()
67
813
        } else if index == 1 {
68
3
            storage.empty_vector().clone()
69
        } else {
70
810
            self.indexed_set.get(&index).unwrap().clone()
71
        }
72
1305
    }
73
}
74

            
75
impl Default for SylvanReader {
76
    fn default() -> Self {
77
        Self::new()
78
    }
79
}
80

            
81
/// Returns a single u32 read from the given stream.
82
191
pub fn read_u32(stream: &mut impl Read) -> Result<u32, MercError> {
83
191
    let mut buffer: [u8; 4] = Default::default();
84
191
    stream.read_exact(&mut buffer)?;
85

            
86
191
    Ok(u32::from_le_bytes(buffer))
87
191
}
88

            
89
/// Returns a single u64 read from the given stream.
90
460
pub fn read_u64(stream: &mut impl Read) -> Result<u64, MercError> {
91
460
    let mut buffer: [u8; 8] = Default::default();
92
460
    stream.read_exact(&mut buffer)?;
93

            
94
460
    Ok(u64::from_le_bytes(buffer))
95
460
}