1use std::borrow::Cow;
2use std::iter::Cloned;
3use std::slice::Iter;
4
5use super::{OwnedSegment, PathPrefix, TargetPath, ValuePath};
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub struct BorrowedValuePath<'a, 'b> {
9 pub segments: &'b [BorrowedSegment<'a>],
10}
11
12#[derive(Clone, Copy, Debug, Eq, PartialEq)]
13pub struct BorrowedTargetPath<'a, 'b> {
14 pub prefix: PathPrefix,
15 pub path: BorrowedValuePath<'a, 'b>,
16}
17
18impl<'a, 'b> BorrowedTargetPath<'a, 'b> {
19 pub fn event(path: BorrowedValuePath<'a, 'b>) -> Self {
20 Self {
21 prefix: PathPrefix::Event,
22 path,
23 }
24 }
25
26 pub fn metadata(path: BorrowedValuePath<'a, 'b>) -> Self {
27 Self {
28 prefix: PathPrefix::Metadata,
29 path,
30 }
31 }
32}
33
34#[derive(Debug, PartialEq, Eq, Clone)]
35pub enum BorrowedSegment<'a> {
36 Field(Cow<'a, str>),
37 Index(isize),
38 Invalid,
39}
40
41impl BorrowedSegment<'_> {
42 pub const fn field(value: &str) -> BorrowedSegment<'_> {
43 BorrowedSegment::Field(Cow::Borrowed(value))
44 }
45 pub fn index(value: isize) -> BorrowedSegment<'static> {
46 BorrowedSegment::Index(value)
47 }
48 pub fn is_field(&self) -> bool {
49 matches!(self, BorrowedSegment::Field(_))
50 }
51 pub fn is_index(&self) -> bool {
52 matches!(self, BorrowedSegment::Index(_))
53 }
54 pub fn is_invalid(&self) -> bool {
55 matches!(self, BorrowedSegment::Invalid)
56 }
57}
58
59impl<'a> From<&'a OwnedSegment> for BorrowedSegment<'a> {
60 fn from(segment: &'a OwnedSegment) -> Self {
61 match segment {
62 OwnedSegment::Field(field) => Self::Field(field.as_str().into()),
63 OwnedSegment::Index(i) => Self::Index(*i),
64 }
65 }
66}
67
68impl<'a> From<&'a str> for BorrowedSegment<'a> {
69 fn from(field: &'a str) -> Self {
70 BorrowedSegment::field(field)
71 }
72}
73
74impl<'a> From<&'a String> for BorrowedSegment<'a> {
75 fn from(field: &'a String) -> Self {
76 BorrowedSegment::field(field.as_str())
77 }
78}
79
80impl From<isize> for BorrowedSegment<'_> {
81 fn from(index: isize) -> Self {
82 BorrowedSegment::index(index)
83 }
84}
85
86impl<'a, 'b> ValuePath<'a> for BorrowedValuePath<'a, 'b> {
87 type Iter = Cloned<Iter<'b, BorrowedSegment<'a>>>;
88
89 fn segment_iter(&self) -> Self::Iter {
90 self.segments.iter().cloned()
91 }
92}
93
94impl<'a, 'b> ValuePath<'a> for &'b Vec<BorrowedSegment<'a>> {
95 type Iter = Cloned<Iter<'b, BorrowedSegment<'a>>>;
96
97 fn segment_iter(&self) -> Self::Iter {
98 self.as_slice().iter().cloned()
99 }
100}
101
102impl<'a, 'b> TargetPath<'a> for BorrowedTargetPath<'a, 'b> {
103 type ValuePath = BorrowedValuePath<'a, 'b>;
104
105 fn prefix(&self) -> PathPrefix {
106 self.prefix
107 }
108
109 fn value_path(&self) -> Self::ValuePath {
110 self.path
111 }
112}
113
114#[cfg(any(test, feature = "arbitrary"))]
115impl quickcheck::Arbitrary for BorrowedSegment<'static> {
116 fn arbitrary(g: &mut quickcheck::Gen) -> Self {
117 if bool::arbitrary(g) {
118 if bool::arbitrary(g) {
119 BorrowedSegment::Index((usize::arbitrary(g) % 20) as isize)
120 } else {
121 BorrowedSegment::Index(-((usize::arbitrary(g) % 20) as isize))
122 }
123 } else {
124 BorrowedSegment::Field(String::arbitrary(g).into())
125 }
126 }
127
128 fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
129 match self {
130 BorrowedSegment::Invalid => Box::new(std::iter::empty()),
131 BorrowedSegment::Index(index) => Box::new(index.shrink().map(BorrowedSegment::Index)),
132 BorrowedSegment::Field(field) => Box::new(
133 field
134 .to_string()
135 .shrink()
136 .map(|f| BorrowedSegment::Field(f.into())),
137 ),
138 }
139 }
140}