ironplc_dsl/
core.rs

1use core::fmt;
2use std::{cmp::Ordering, hash::Hash, hash::Hasher};
3
4/// Implements Identifier declared by 2.1.2.
5///
6/// 61131-3 declares that identifiers are case insensitive.
7/// This class ensures that we do case insensitive comparisons
8/// and can use containers as appropriate.
9#[derive(Clone)]
10pub struct Id {
11    original: String,
12    lower_case: String,
13}
14
15impl Id {
16    /// Converts a `&str` into an `Identifier`.
17    pub fn from(str: &str) -> Id {
18        Id {
19            original: String::from(str),
20            lower_case: String::from(str).to_lowercase(),
21        }
22    }
23
24    /// Returns a copy of the value.
25    pub fn clone(&self) -> Id {
26        Id::from(self.original.as_str())
27    }
28
29    /// Converts an `Identifier` into a `String`.
30    ///
31    /// The `String` representation is such that comparison
32    /// to other `String` objects generated by `Identifier`
33    /// are equal.
34    pub fn to_string(&self) -> String {
35        String::from(&self.lower_case)
36    }
37
38    /// Converts an `Identifier` into a lower case `String`.
39    pub fn lower_case(&self) -> &String {
40        &self.lower_case
41    }
42}
43
44impl PartialEq for Id {
45    fn eq(&self, other: &Self) -> bool {
46        self.lower_case == other.lower_case
47    }
48}
49impl Eq for Id {}
50
51impl Hash for Id {
52    fn hash<H: Hasher>(&self, state: &mut H) {
53        self.lower_case.hash(state);
54    }
55}
56
57impl Ord for Id {
58    fn cmp(&self, other: &Self) -> Ordering {
59        self.lower_case.cmp(&other.lower_case)
60    }
61}
62
63impl PartialOrd for Id {
64    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
65        Some(self.cmp(other))
66    }
67}
68
69impl fmt::Debug for Id {
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        f.write_str(&self.original)
72    }
73}
74
75impl fmt::Display for Id {
76    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77        f.write_str(&self.original)
78    }
79}
80
81// TODO it is very questionable to have this part of equality
82#[derive(Debug, Clone)]
83pub struct SourceLoc {
84    pub offset: usize,
85}
86
87impl SourceLoc {
88    pub fn new(offset: usize) -> SourceLoc {
89        SourceLoc { offset: offset }
90    }
91}
92
93impl PartialEq for SourceLoc {
94    fn eq(&self, other: &Self) -> bool {
95        // TODO this is dubious - two source locations are equal? But to some
96        // degree this is true because we don't care about the location for
97        // equality purposes.
98        true
99    }
100}
101impl Eq for SourceLoc {}