1use std::fmt::{Debug, Display, Formatter};
2use std::num::NonZeroU32;
3use tanzim_source::Source;
4
5#[derive(Debug, Clone, PartialEq)]
13pub struct Location {
14 pub source: Source,
16 pub line: Option<NonZeroU32>,
18 pub column: Option<NonZeroU32>,
20 pub length: Option<NonZeroU32>,
22 pub snippet: String,
27}
28
29fn position(value: usize) -> Option<NonZeroU32> {
34 NonZeroU32::new(u32::try_from(value).unwrap_or(u32::MAX))
35}
36
37impl Location {
38 pub fn in_source(
43 source: Source,
44 line: Option<usize>,
45 column: Option<usize>,
46 length: Option<usize>,
47 ) -> Self {
48 Self {
49 source,
50 line: line.and_then(position),
51 column: column.and_then(position),
52 length: length.and_then(position),
53 snippet: String::new(),
54 }
55 }
56
57 pub fn in_text(
63 source: Source,
64 text: &str,
65 line: Option<usize>,
66 column: Option<usize>,
67 length: Option<usize>,
68 ) -> Self {
69 let mut snippet = String::new();
70 if let Some(line_number) = line {
71 let highlight = length.unwrap_or(1).max(1);
72 let lines: Vec<&str> = text.split('\n').collect();
73 let offending = line_number.saturating_sub(1);
74 let start = offending.saturating_sub(3);
75 let end = (offending + 4).min(lines.len());
76 let gutter_width = end.to_string().len();
77 let mut rows: Vec<String> = Vec::new();
78 for (offset, line_text) in lines[start..end].iter().enumerate() {
79 let display_line = start + offset + 1;
80 let number = display_line.to_string();
81 let pad = gutter_width.saturating_sub(number.len());
82 let mut row = String::from(" ");
83 for _ in 0..pad {
84 row.push(' ');
85 }
86 row.push_str(&number);
87 row.push_str(" | ");
88 row.push_str(line_text);
89 rows.push(row);
90 if display_line == line_number {
91 let mut caret = String::from(" ");
92 for _ in 0..pad + number.len() + 1 {
93 caret.push(' ');
94 }
95 caret.push_str("| ");
96 if let Some(column_number) = column {
97 for _ in 1..column_number {
98 caret.push(' ');
99 }
100 }
101 for _ in 0..highlight {
102 caret.push('^');
103 }
104 rows.push(caret);
105 }
106 }
107 snippet = rows.join("\n");
108 }
109 Self {
110 source,
111 line: line.and_then(position),
112 column: column.and_then(position),
113 length: length.and_then(position),
114 snippet,
115 }
116 }
117
118 pub fn at(
121 source_name: &str,
122 resource: &str,
123 line: Option<usize>,
124 column: Option<usize>,
125 length: Option<usize>,
126 ) -> Self {
127 Self::in_source(
128 Source::named(source_name).with_resource(resource),
129 line,
130 column,
131 length,
132 )
133 }
134
135 pub fn source_name(&self) -> &str {
137 self.source.source()
138 }
139
140 pub fn resource(&self) -> &str {
142 self.source.resource()
143 }
144
145 pub fn with_length(mut self, length: usize) -> Self {
147 self.length = position(length);
148 self
149 }
150}
151
152impl Display for Location {
153 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
154 let resource = self.source.resource();
155 if resource.is_empty() {
156 write!(f, "{}", self.source.source())?;
157 } else {
158 write!(f, "{}:{}", self.source.source(), resource)?;
159 }
160 match (self.line, self.column) {
161 (Some(line), Some(column)) => write!(f, ":{line}:{column}"),
162 (Some(line), None) => write!(f, ":{line}"),
163 _ => Ok(()),
164 }
165 }
166}
167
168#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
170pub enum ValueType {
171 Bool,
173 Int,
175 Float,
177 String,
179 List,
181 Map,
183 Null,
185}
186
187impl Display for ValueType {
188 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
189 f.write_str(match self {
190 Self::Bool => "boolean",
191 Self::Int => "integer",
192 Self::Float => "float",
193 Self::String => "string",
194 Self::List => "list",
195 Self::Map => "map",
196 Self::Null => "null",
197 })
198 }
199}
200
201#[derive(Debug, Clone, PartialEq, Default)]
226pub struct Map {
227 entries: Vec<(String, LocatedValue)>,
228}
229
230impl Map {
231 pub fn new() -> Self {
233 Self::default()
234 }
235
236 pub fn len(&self) -> usize {
238 self.entries.len()
239 }
240
241 pub fn is_empty(&self) -> bool {
243 self.entries.is_empty()
244 }
245
246 pub fn contains_key(&self, key: &str) -> bool {
248 for index in (0..self.entries.len()).rev() {
249 if self.entries[index].0 == key {
250 return true;
251 }
252 }
253 false
254 }
255
256 pub fn get(&self, key: &str) -> Option<&LocatedValue> {
259 for index in (0..self.entries.len()).rev() {
260 if self.entries[index].0 == key {
261 return Some(&self.entries[index].1);
262 }
263 }
264 None
265 }
266
267 pub fn get_mut(&mut self, key: &str) -> Option<&mut LocatedValue> {
269 let mut found = None;
270 for index in (0..self.entries.len()).rev() {
271 if self.entries[index].0 == key {
272 found = Some(index);
273 break;
274 }
275 }
276 if let Some(index) = found {
277 Some(&mut self.entries[index].1)
278 } else {
279 None
280 }
281 }
282
283 pub fn insert(&mut self, key: String, value: LocatedValue) -> Option<LocatedValue> {
285 let old = self.remove(&key);
286 self.entries.push((key, value));
287 old
288 }
289
290 pub fn remove(&mut self, key: &str) -> Option<LocatedValue> {
292 let mut found = None;
293 for index in (0..self.entries.len()).rev() {
294 if self.entries[index].0 == key {
295 found = Some(index);
296 break;
297 }
298 }
299 if let Some(index) = found {
300 Some(self.entries.remove(index).1)
301 } else {
302 None
303 }
304 }
305
306 pub fn entries(&self) -> &[(String, LocatedValue)] {
308 &self.entries
309 }
310
311 pub fn entries_mut(&mut self) -> &mut Vec<(String, LocatedValue)> {
313 &mut self.entries
314 }
315}
316
317impl Display for Map {
318 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
319 let alternate = f.alternate();
320 let mut map = f.debug_map();
321 for (key, value) in &self.entries {
322 if alternate {
323 map.entry(key, &format_args!("{:#}", value));
324 } else {
325 map.entry(key, &format_args!("{}", value));
326 }
327 }
328 map.finish()
329 }
330}
331
332#[derive(Debug, Clone, PartialEq)]
349pub enum Value {
350 Bool(bool),
352 Int(isize),
354 Float(f64),
356 String(String),
358 List(Vec<LocatedValue>),
360 Map(Map),
362 Null,
364}
365
366impl From<bool> for Value {
367 fn from(value: bool) -> Self {
368 Value::Bool(value)
369 }
370}
371
372impl From<isize> for Value {
373 fn from(value: isize) -> Self {
374 Value::Int(value)
375 }
376}
377
378impl From<f64> for Value {
379 fn from(value: f64) -> Self {
380 Value::Float(value)
381 }
382}
383
384impl From<String> for Value {
385 fn from(value: String) -> Self {
386 Value::String(value)
387 }
388}
389
390impl From<&str> for Value {
391 fn from(value: &str) -> Self {
392 Value::String(value.to_string())
393 }
394}
395
396#[derive(Debug, Clone, PartialEq, Default)]
401pub struct Comment {
402 before: Vec<String>,
403 after: Option<String>,
404}
405
406impl Comment {
407 pub fn new() -> Self {
409 Self::default()
410 }
411
412 pub fn before(&self) -> &[String] {
414 &self.before
415 }
416
417 pub fn before_mut(&mut self) -> &mut Vec<String> {
419 &mut self.before
420 }
421
422 pub fn after(&self) -> Option<&str> {
424 self.after.as_deref()
425 }
426
427 pub fn after_mut(&mut self) -> &mut Option<String> {
429 &mut self.after
430 }
431
432 pub fn with_before(mut self, lines: impl IntoIterator<Item = impl Into<String>>) -> Self {
434 self.before = lines.into_iter().map(|l| l.into()).collect();
435 self
436 }
437
438 pub fn with_after(mut self, text: Option<impl Into<String>>) -> Self {
440 self.after = text.map(|t| t.into());
441 self
442 }
443
444 pub fn set_before(&mut self, lines: impl IntoIterator<Item = impl Into<String>>) {
446 self.before = lines.into_iter().map(|l| l.into()).collect();
447 }
448
449 pub fn set_after(&mut self, text: Option<impl Into<String>>) {
451 self.after = text.map(|t| t.into());
452 }
453}
454
455#[derive(Debug, Clone, PartialEq)]
472pub struct LocatedValue {
473 value: Value,
474 location: Location,
475 comment: Comment,
476}
477
478impl LocatedValue {
479 pub fn new(value: impl Into<Value>, location: impl Into<Location>) -> Self {
481 Self {
482 value: value.into(),
483 location: location.into(),
484 comment: Comment::new(),
485 }
486 }
487
488 pub fn value(&self) -> &Value {
492 &self.value
493 }
494
495 pub fn value_mut(&mut self) -> &mut Value {
497 &mut self.value
498 }
499
500 pub fn into_value(self) -> Value {
502 self.value
503 }
504
505 pub fn with_value(mut self, value: impl Into<Value>) -> Self {
507 self.value = value.into();
508 self
509 }
510
511 pub fn set_value(&mut self, value: impl Into<Value>) {
513 self.value = value.into();
514 }
515
516 pub fn location(&self) -> &Location {
520 &self.location
521 }
522
523 pub fn location_mut(&mut self) -> &mut Location {
525 &mut self.location
526 }
527
528 pub fn with_location(mut self, location: impl Into<Location>) -> Self {
530 self.location = location.into();
531 self
532 }
533
534 pub fn set_location(&mut self, location: impl Into<Location>) {
536 self.location = location.into();
537 }
538
539 pub fn comment(&self) -> &Comment {
543 &self.comment
544 }
545
546 pub fn comment_mut(&mut self) -> &mut Comment {
548 &mut self.comment
549 }
550
551 pub fn with_comment(mut self, comment: Comment) -> Self {
553 self.comment = comment;
554 self
555 }
556
557 pub fn set_comment(&mut self, comment: Comment) {
559 self.comment = comment;
560 }
561}
562
563impl Display for LocatedValue {
564 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
565 if f.alternate() {
566 let mut map = f.debug_map();
567 map.entry(&"value", &format_args!("{:#}", self.value));
568 map.entry(
569 &"location",
570 &format_args!("{:?}", self.location.to_string()),
571 );
572 if !self.comment.before.is_empty() || self.comment.after.is_some() {
573 map.entry(&"comment_before", &self.comment.before.as_slice());
574 if let Some(after) = &self.comment.after {
575 map.entry(&"comment_after", &after.as_str());
576 }
577 }
578 map.finish()
579 } else {
580 write!(f, "{}", self.value)
581 }
582 }
583}
584
585impl AsRef<Value> for Value {
586 fn as_ref(&self) -> &Value {
587 self
588 }
589}
590
591impl AsRef<Value> for LocatedValue {
592 fn as_ref(&self) -> &Value {
593 &self.value
594 }
595}
596
597impl Value {
598 pub fn new_map() -> Self {
600 Self::Map(Map::new())
601 }
602
603 pub fn new_list() -> Self {
605 Self::List(Vec::new())
606 }
607
608 pub fn new_string() -> Self {
610 Self::String(String::new())
611 }
612
613 pub fn is_bool(&self) -> bool {
615 matches!(self, Self::Bool(_))
616 }
617
618 pub fn as_bool(&self) -> Option<bool> {
620 match self {
621 Self::Bool(value) => Some(*value),
622 _ => None,
623 }
624 }
625
626 pub fn into_bool(self) -> Option<bool> {
628 match self {
629 Self::Bool(value) => Some(value),
630 _ => None,
631 }
632 }
633
634 pub fn bool_mut(&mut self) -> Option<&mut bool> {
636 match self {
637 Self::Bool(value) => Some(value),
638 _ => None,
639 }
640 }
641
642 pub fn is_int(&self) -> bool {
644 matches!(self, Self::Int(_))
645 }
646
647 pub fn as_int(&self) -> Option<isize> {
649 match self {
650 Self::Int(value) => Some(*value),
651 _ => None,
652 }
653 }
654
655 pub fn into_int(self) -> Option<isize> {
657 match self {
658 Self::Int(value) => Some(value),
659 _ => None,
660 }
661 }
662
663 pub fn int_mut(&mut self) -> Option<&mut isize> {
665 match self {
666 Self::Int(value) => Some(value),
667 _ => None,
668 }
669 }
670
671 pub fn is_float(&self) -> bool {
673 matches!(self, Self::Float(_))
674 }
675
676 pub fn as_float(&self) -> Option<f64> {
678 match self {
679 Self::Float(value) => Some(*value),
680 _ => None,
681 }
682 }
683
684 pub fn into_float(self) -> Option<f64> {
686 match self {
687 Self::Float(value) => Some(value),
688 _ => None,
689 }
690 }
691
692 pub fn float_mut(&mut self) -> Option<&mut f64> {
694 match self {
695 Self::Float(value) => Some(value),
696 _ => None,
697 }
698 }
699
700 pub fn is_string(&self) -> bool {
702 matches!(self, Self::String(_))
703 }
704
705 pub fn as_string(&self) -> Option<&String> {
707 match self {
708 Self::String(value) => Some(value),
709 _ => None,
710 }
711 }
712
713 pub fn into_string(self) -> Option<String> {
715 match self {
716 Self::String(value) => Some(value),
717 _ => None,
718 }
719 }
720
721 pub fn string_mut(&mut self) -> Option<&mut String> {
723 match self {
724 Self::String(value) => Some(value),
725 _ => None,
726 }
727 }
728
729 pub fn is_list(&self) -> bool {
731 matches!(self, Self::List(_))
732 }
733
734 pub fn as_list(&self) -> Option<&Vec<LocatedValue>> {
736 match self {
737 Self::List(value) => Some(value),
738 _ => None,
739 }
740 }
741
742 pub fn into_list(self) -> Option<Vec<LocatedValue>> {
744 match self {
745 Self::List(value) => Some(value),
746 _ => None,
747 }
748 }
749
750 pub fn list_mut(&mut self) -> Option<&mut Vec<LocatedValue>> {
752 match self {
753 Self::List(value) => Some(value),
754 _ => None,
755 }
756 }
757
758 pub fn is_map(&self) -> bool {
760 matches!(self, Self::Map(_))
761 }
762
763 pub fn as_map(&self) -> Option<&Map> {
765 match self {
766 Self::Map(value) => Some(value),
767 _ => None,
768 }
769 }
770
771 pub fn into_map(self) -> Option<Map> {
773 match self {
774 Self::Map(value) => Some(value),
775 _ => None,
776 }
777 }
778
779 pub fn map_mut(&mut self) -> Option<&mut Map> {
781 match self {
782 Self::Map(value) => Some(value),
783 _ => None,
784 }
785 }
786
787 pub fn is_null(&self) -> bool {
789 matches!(self, Self::Null)
790 }
791
792 pub fn type_name(&self) -> ValueType {
794 match self {
795 Self::Bool(_) => ValueType::Bool,
796 Self::Int(_) => ValueType::Int,
797 Self::Float(_) => ValueType::Float,
798 Self::String(_) => ValueType::String,
799 Self::List(_) => ValueType::List,
800 Self::Map(_) => ValueType::Map,
801 Self::Null => ValueType::Null,
802 }
803 }
804}
805
806impl Display for Value {
807 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
808 match self {
809 Self::Bool(value) => write!(f, "{value}"),
810 Self::Int(value) => write!(f, "{value}"),
811 Self::Float(value) => write!(f, "{value}"),
812 Self::String(value) => write!(f, "{value:?}"),
813 Self::List(values) => {
814 let alternate = f.alternate();
815 let mut list = f.debug_list();
816 for value in values {
817 if alternate {
818 list.entry(&format_args!("{:#}", value));
819 } else {
820 list.entry(&format_args!("{}", value));
821 }
822 }
823 list.finish()
824 }
825 Self::Map(value) => Display::fmt(value, f),
826 Self::Null => f.write_str("null"),
827 }
828 }
829}