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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
//! The matrix holds all modules in a QR code.
//!
//! They're organized in a 2-dimensional grid but held in
//! a vector internally.
//!
//! The implementation uses assertions heavily to ensure correctness.
//! If interfacing with the matrix directly take care not to violate
//! assumptions, like overwriting existing data.

use std::ops::Not;

/// The type of a module.
/// Differentiates the different types during construction,
/// a valid QR code should only hold function and data modules.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Module {
    /// An unknown module, it hasn't been assigned yet.
    Unknown,
    /// Reserved module.
    /// Version and format info uses this to reserve modules before masking.
    Reserved,
    /// Function module, contains QR code artifacts like finders and timing patterns.
    Function(bool),
    /// Data module. Contains both data and error codes.
    Data(bool),
}

impl Module {
    /// Is the module dark?
    /// Only makes sense for data or function modules.
    pub fn is_dark(&self) -> bool {
        match self {
            Module::Unknown => false,
            Module::Reserved => false,
            Module::Function(v) => *v,
            Module::Data(v) => *v,
        }
    }

    /// Is the module a function module?
    /// This includes reserved modules as well.
    pub fn is_fun(&self) -> bool {
        match self {
            Module::Unknown => false,
            Module::Data(_) => false,
            _ => true,
        }
    }

    /// Is the module a Data module?
    pub fn is_data(&self) -> bool {
        match self {
            Module::Data(_) => true,
            _ => false,
        }
    }
}

impl Not for Module {
    type Output = Module;
    fn not(self) -> Module {
        match self {
            Module::Unknown => Module::Unknown,
            Module::Reserved => Module::Reserved,
            Module::Function(v) => Module::Function(!v),
            Module::Data(v) => Module::Data(!v),
        }
    }
}

/// Matrix is a 2-dimensional grid holding the QR modules.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Matrix {
    /// Size defines the width and height of the matrix.
    pub size: usize,

    /// The modules.
    pub modules: Vec<Module>,
}

impl Matrix {
    /// Create a new matrix, modules initialized to Unknown.
    pub fn new(size: usize) -> Matrix {
        Matrix {
            size: size,
            modules: vec![Module::Unknown; size * size],
        }
    }

    /// Map (x,y) coords to linear index.
    pub fn index(&self, x: usize, y: usize) -> usize {
        assert!(x < self.size);
        assert!(y < self.size);
        self.size * y + x
    }

    /// Get module.
    pub fn get(&self, x: usize, y: usize) -> &Module {
        &self.modules[self.index(x, y)]
    }

    /// Get mutable module.
    pub fn get_mut(&mut self, x: usize, y: usize) -> &mut Module {
        let i = self.index(x, y);
        &mut self.modules[i]
    }

    /// Returns true if the module at x,y is dark.
    pub fn is_dark(&self, x: usize, y: usize) -> bool {
        self.get(x, y).is_dark()
    }

    /// Return true if the module at x,y is a function module.
    pub fn is_fun(&self, x: usize, y: usize) -> bool {
        self.get(x, y).is_fun()
    }

    /// Return true if the module at x,y contains data.
    pub fn is_data(&self, x: usize, y: usize) -> bool {
        self.get(x, y).is_data()
    }

    /// Assign a module.
    pub fn set(&mut self, x: usize, y: usize, v: Module) {
        *self.get_mut(x, y) = v;
    }

    /// Assign a function module.
    /// Fails if the existing module is a Data module.
    pub fn set_fun(&mut self, x: usize, y: usize, v: bool) {
        let m = self.get_mut(x, y);
        assert!(!m.is_data());
        *m = Module::Function(v);
    }

    /// Assign a data module.
    /// Fails unless the existing module is Unknown.
    pub fn set_data(&mut self, x: usize, y: usize, v: bool) {
        let m = self.get_mut(x, y);
        assert!(*m == Module::Unknown);
        *m = Module::Data(v);
    }

    /// Flip a module.
    /// Fails unless it's a data module.
    pub fn flip(&mut self, x: usize, y: usize) {
        let m = self.get_mut(x, y);
        assert!(m.is_data());
        *m = !*m;
    }

    /// Set square outline.
    pub fn set_square_outline(&mut self, x: usize, y: usize, w: usize, v: Module) {
        // Above and below
        for a in x..(x + w) {
            self.set(a, y, v);
            self.set(a, y + w - 1, v);
        }
        // Left and right
        for b in (y + 1)..(y + w - 1) {
            self.set(x, b, v);
            self.set(x + w - 1, b, v);
        }
    }

    /// Set square.
    pub fn set_square(&mut self, x: usize, y: usize, w: usize, v: Module) {
        self.set_rect(x, y, x + w - 1, y + w - 1, v);
    }

    /// Set rect.
    pub fn set_rect(&mut self, x0: usize, y0: usize, x1: usize, y1: usize, v: Module) {
        for a in x0..(x1 + 1) {
            for b in y0..(y1 + 1) {
                self.set(a, b, v);
            }
        }
    }

    /// Return true if there's any module other than Unknown in square.
    pub fn any_in_square(&self, x: usize, y: usize, w: usize) -> bool {
        self.any_in_rect(x, y, x + w - 1, y + w - 1)
    }

    /// Return true if there's any module other than Unknown in rect.
    pub fn any_in_rect(&self, x0: usize, y0: usize, x1: usize, y1: usize) -> bool {
        for a in x0..(x1 + 1) {
            for b in y0..(y1 + 1) {
                if *self.get(a, b) != Module::Unknown {
                    return true;
                }
            }
        }
        false
    }

    /// Return true if the matrix is complete, that's if it only contains
    /// Data or Function modules.
    pub fn complete(&self) -> bool {
        for m in self.modules.iter() {
            match m {
                Module::Unknown => return false,
                Module::Reserved => return false,
                _ => {},
            }
        }
        true
    }
}