dzn_rs/
value.rs

1use std::collections::HashSet;
2
3use crate::numbers::Integer;
4
5/// A primitive MiniZinc value.
6#[derive(Clone, Debug)]
7pub enum Value<Int> {
8    Bool(bool),
9    Int(Int),
10    SetOfInt(HashSet<Int>),
11}
12
13/// Helper trait to extract values from enums.
14pub trait GetValue<T> {
15    /// If the enum is `T`, then return the value. Otherwise, return `None`.
16    fn try_get(&self) -> Option<&T>;
17}
18
19impl<Int> GetValue<bool> for Value<Int> {
20    fn try_get(&self) -> Option<&bool> {
21        match self {
22            Value::Bool(boolean) => Some(boolean),
23            _ => None,
24        }
25    }
26}
27
28impl<Int: Integer> GetValue<Int> for Value<Int> {
29    fn try_get(&self) -> Option<&Int> {
30        match self {
31            Value::Int(int) => Some(int),
32            _ => None,
33        }
34    }
35}
36
37impl<Int: Integer> GetValue<HashSet<Int>> for Value<Int> {
38    fn try_get(&self) -> Option<&HashSet<Int>> {
39        match self {
40            Value::SetOfInt(set) => Some(set),
41            _ => None,
42        }
43    }
44}
45
46/// The possible arrays of values.
47///
48/// `DIM` is either 1 or 2, depending on whether we have a 1 dimensional or 2-dimensional array.
49#[derive(Clone, Debug)]
50pub enum ValueArray<Int, const DIM: usize> {
51    Bool(ShapedArray<bool, DIM>),
52    Int(ShapedArray<Int, DIM>),
53    SetOfInt(ShapedArray<HashSet<Int>, DIM>),
54}
55
56impl<Int: Integer, const DIM: usize> GetValue<ShapedArray<bool, DIM>> for ValueArray<Int, DIM> {
57    fn try_get(&self) -> Option<&ShapedArray<bool, DIM>> {
58        match self {
59            ValueArray::Bool(array) => Some(array),
60            _ => None,
61        }
62    }
63}
64
65impl<Int, const DIM: usize> GetValue<ShapedArray<Int, DIM>> for ValueArray<Int, DIM> {
66    fn try_get(&self) -> Option<&ShapedArray<Int, DIM>> {
67        match self {
68            ValueArray::Int(array) => Some(array),
69            _ => None,
70        }
71    }
72}
73
74impl<Int, const DIM: usize> GetValue<ShapedArray<HashSet<Int>, DIM>> for ValueArray<Int, DIM> {
75    fn try_get(&self) -> Option<&ShapedArray<HashSet<Int>, DIM>> {
76        match self {
77            ValueArray::SetOfInt(set) => Some(set),
78            _ => None,
79        }
80    }
81}
82
83/// 1d or 2d array of values.
84#[derive(Clone, Debug)]
85pub struct ShapedArray<T, const DIM: usize> {
86    pub(crate) shape: [usize; DIM],
87    pub(crate) elements: Vec<T>,
88}
89
90impl<T, const D: usize> ShapedArray<T, D> {
91    /// Get the shape of the multi-dimensional array.
92    pub fn shape(&self) -> &[usize; D] {
93        &self.shape
94    }
95
96    /// Get a value from the array with the given path.
97    ///
98    /// The path is an iterator of indices into each of the dimensions of the array.
99    pub fn get(&self, path: [usize; D]) -> Option<&T> {
100        let index = match D {
101            1 => path[0],
102            2 => path[0] * self.shape[1] + path[1],
103            _ => panic!("Arrays with higher than 2 dimensions are not supported"),
104        };
105
106        self.elements.get(index)
107    }
108}