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#[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}