1#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
19pub struct Position {
20 line: usize,
22 column: usize,
24 byte_offset: usize,
26}
27
28impl Position {
29 pub fn new(line: usize, column: usize, byte_offset: usize) -> Self {
45 Self {
46 line,
47 column,
48 byte_offset,
49 }
50 }
51
52 pub fn line(&self) -> usize {
54 self.line
55 }
56
57 pub fn column(&self) -> usize {
59 self.column
60 }
61
62 pub fn byte_offset(&self) -> usize {
64 self.byte_offset
65 }
66}
67
68#[cfg(feature = "serde")]
69impl serde::Serialize for Position {
70 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
71 where
72 S: serde::Serializer,
73 {
74 use serde::ser::SerializeStruct;
75 let mut state = serializer.serialize_struct("Position", 3)?;
76 state.serialize_field("line", &self.line)?;
77 state.serialize_field("column", &self.column)?;
78 state.serialize_field("byte_offset", &self.byte_offset)?;
79 state.end()
80 }
81}
82
83#[cfg(feature = "serde")]
84impl<'de> serde::Deserialize<'de> for Position {
85 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
86 where
87 D: serde::Deserializer<'de>,
88 {
89 use serde::de::{self, MapAccess, Visitor};
90 use std::fmt;
91
92 struct PositionVisitor;
93
94 impl<'de> Visitor<'de> for PositionVisitor {
95 type Value = Position;
96
97 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
98 formatter.write_str("struct Position")
99 }
100
101 fn visit_map<V>(self, mut map: V) -> Result<Position, V::Error>
102 where
103 V: MapAccess<'de>,
104 {
105 let mut line = None;
106 let mut column = None;
107 let mut byte_offset = None;
108 while let Some(key) = map.next_key()? {
109 match key {
110 "line" => {
111 if line.is_some() {
112 return Err(de::Error::duplicate_field("line"));
113 }
114 line = Some(map.next_value()?);
115 }
116 "column" => {
117 if column.is_some() {
118 return Err(de::Error::duplicate_field("column"));
119 }
120 column = Some(map.next_value()?);
121 }
122 "byte_offset" => {
123 if byte_offset.is_some() {
124 return Err(de::Error::duplicate_field("byte_offset"));
125 }
126 byte_offset = Some(map.next_value()?);
127 }
128 _ => {
129 let _ = map.next_value::<de::IgnoredAny>()?;
130 }
131 }
132 }
133 let line = line.ok_or_else(|| de::Error::missing_field("line"))?;
134 let column = column.ok_or_else(|| de::Error::missing_field("column"))?;
135 let byte_offset =
136 byte_offset.ok_or_else(|| de::Error::missing_field("byte_offset"))?;
137 Ok(Position::new(line, column, byte_offset))
138 }
139 }
140
141 const FIELDS: &[&str] = &["line", "column", "byte_offset"];
142 deserializer.deserialize_struct("Position", FIELDS, PositionVisitor)
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149
150 #[test]
151 fn test_position_creation() {
152 let pos = Position::new(1, 5, 10);
153 assert_eq!(pos.line(), 1);
154 assert_eq!(pos.column(), 5);
155 assert_eq!(pos.byte_offset(), 10);
156 }
157}