text_parsing/
locality.rs

1use crate::Error;
2
3use std::fmt;
4
5#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
6pub struct Snip {
7    pub offset: usize,
8    pub length: usize,
9}
10impl fmt::Debug for Snip {
11    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12        write!(f, "{}(+{})", self.offset, self.length)
13    }
14}
15
16pub trait Localize: Sized {
17    fn localize(self, chars: Snip, bytes: Snip) -> Local<Self> {
18        Local {
19            chars,
20            bytes,
21            data: self,
22        }
23    }
24}
25impl<T: Sized> Localize for T {}
26
27/*impl fmt::Debug for Local<()> {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        f.debug_struct("Local")
30            .field("bytes", &self.bytes)
31            .field("chars", &self.chars)
32            .finish()
33    }
34}*/
35
36#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
37pub struct Local<E> {
38    chars: Snip,
39    bytes: Snip,
40    data: E,
41}
42impl<E> Local<E> {
43    pub fn into_inner(self) -> (Local<()>, E) {
44        (
45            Local {
46                chars: self.chars,
47                bytes: self.bytes,
48                data: (),
49            },
50            self.data,
51        )
52    }
53    pub fn data(&self) -> &E {
54        &self.data
55    }
56    pub fn chars(&self) -> Snip {
57        self.chars
58    }
59    pub fn bytes(&self) -> Snip {
60        self.bytes
61    }
62
63    pub fn into_position(mut self) -> Local<E> {
64        self.chars.length = 0;
65        self.bytes.length = 0;
66        self
67    }
68
69    pub fn local<T>(&self, data: T) -> Local<T> {
70        Local {
71            chars: self.chars,
72            bytes: self.bytes,
73            data,
74        }
75    }
76    pub fn map<F, T>(self, mut mapper: F) -> Local<T>
77    where
78        F: FnMut(E) -> T,
79    {
80        Local {
81            chars: self.chars,
82            bytes: self.bytes,
83            data: mapper(self.data),
84        }
85    }
86    pub fn with_inner<T>(self, inner: T) -> Local<T> {
87        Local {
88            chars: self.chars,
89            bytes: self.bytes,
90            data: inner,
91        }
92    }
93    pub fn with_shift(mut self, char_offset: usize, byte_offset: usize) -> Local<E> {
94        self.chars.offset += char_offset;
95        self.bytes.offset += byte_offset;
96        self
97    }
98
99    pub fn from_segment<T>(begin: Local<E>, end: Local<T>) -> Result<Local<E>, Error> {
100        if (begin.chars.offset <= end.chars.offset) && (begin.bytes.offset <= end.bytes.offset) {
101            Ok(Local {
102                chars: Snip {
103                    offset: begin.chars.offset,
104                    length: end.chars.length + end.chars.offset - begin.chars.offset,
105                },
106                bytes: Snip {
107                    offset: begin.bytes.offset,
108                    length: end.bytes.length + end.bytes.offset - begin.bytes.offset,
109                },
110                data: begin.data,
111            })
112        } else {
113            Err(Error::EndBeforeBegin)
114        }
115    }
116}