1+ use std:: collections:: VecDeque ;
2+
3+ use crate :: schema:: FieldRef ;
4+
5+ /// A struct to hold the parsed components of the location of a node in a compiled tree.
6+ ///
7+ /// An address of a node in the `Content` tree is an array of string names of child nodes, as
8+ /// declared by the node's [`Compile`](super::Compile) implementation.
9+ #[ derive( Debug , Default , Clone , Eq , PartialEq , Hash , Ord , PartialOrd ) ]
10+ pub struct Address ( VecDeque < String > ) ;
11+
12+ impl std:: fmt:: Display for Address {
13+ fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
14+ let mut chunks = self . iter ( ) ;
15+ write ! ( f, "{}" , chunks. next( ) . unwrap_or( "{top-level}" ) ) ?;
16+ for chunk in chunks {
17+ write ! ( f, ".{}" , chunk) ?;
18+ }
19+ Ok ( ( ) )
20+ }
21+ }
22+
23+ impl Address {
24+ #[ inline]
25+ pub fn new_root ( ) -> Self {
26+ Self ( VecDeque :: new ( ) )
27+ }
28+
29+ #[ inline]
30+ pub fn is_root ( & self ) -> bool {
31+ self . 0 . is_empty ( )
32+ }
33+
34+ pub fn root ( & self ) -> Self {
35+ self . iter ( ) . map ( |node| node. to_string ( ) ) . take ( 1 ) . collect ( )
36+ }
37+
38+ #[ inline]
39+ pub fn iter ( & self ) -> impl DoubleEndedIterator < Item = & str > {
40+ self . 0 . iter ( ) . map ( |value| value. as_str ( ) )
41+ }
42+
43+ #[ inline]
44+ pub fn deeper ( & mut self ) -> Option < String > {
45+ self . 0 . pop_front ( )
46+ }
47+
48+ #[ inline]
49+ pub fn shallower ( & mut self ) -> Option < String > {
50+ self . 0 . pop_back ( )
51+ }
52+
53+ #[ inline]
54+ pub fn into_shallower ( mut self ) -> Self {
55+ self . shallower ( ) . unwrap ( ) ;
56+ self
57+ }
58+
59+ #[ inline]
60+ pub fn within ( & mut self , scope : & str ) -> & mut Self {
61+ self . 0 . push_front ( scope. to_string ( ) ) ;
62+ self
63+ }
64+
65+ #[ inline]
66+ pub fn len ( & self ) -> usize {
67+ self . 0 . len ( )
68+ }
69+
70+ #[ inline]
71+ pub fn is_empty ( & self ) -> bool {
72+ self . 0 . is_empty ( )
73+ }
74+
75+ #[ inline]
76+ pub fn into_within ( mut self , scope : & str ) -> Self {
77+ self . within ( scope) ;
78+ self
79+ }
80+
81+ #[ inline]
82+ pub fn at ( & mut self , attribute : & str ) -> & mut Self {
83+ self . 0 . push_back ( attribute. to_string ( ) ) ;
84+ self
85+ }
86+
87+ #[ inline]
88+ pub fn into_at ( mut self , attribute : & str ) -> Self {
89+ self . at ( attribute) ;
90+ self
91+ }
92+
93+ pub fn as_local_to ( & self , root : & Self ) -> Option < Self > {
94+ if root. 0 . len ( ) > self . 0 . len ( ) {
95+ None
96+ } else {
97+ Some (
98+ self . iter ( )
99+ . zip ( root. iter ( ) )
100+ . skip_while ( |( left, right) | left == right)
101+ . map ( |( left, _) | left. to_string ( ) )
102+ . collect ( ) ,
103+ )
104+ }
105+ }
106+
107+ pub fn as_in ( & self , other : & Self ) -> Option < Self > {
108+ let mut out = self . clone ( ) ;
109+ for level in other. iter ( ) {
110+ if * level != out. deeper ( ) ? {
111+ return None ;
112+ }
113+ }
114+ Some ( out)
115+ }
116+
117+ pub fn concat ( & self , other : & Self ) -> Self {
118+ let mut out = self . clone ( ) ;
119+ out. extend ( other. clone ( ) . into_iter ( ) ) ;
120+ out
121+ }
122+
123+ pub fn relativize ( & self , with : & Self ) -> ( Self , Self ) {
124+ let root = self . common_root ( with) ;
125+ let relative = self . as_in ( & root) . unwrap ( ) ;
126+ ( root, relative)
127+ }
128+
129+ pub fn common_root ( & self , other : & Self ) -> Self {
130+ self . iter ( )
131+ . zip ( other. iter ( ) )
132+ . take_while ( |( left, right) | left == right)
133+ . map ( |( left, _) | left. to_string ( ) )
134+ . collect ( )
135+ }
136+ }
137+
138+ impl std:: iter:: FromIterator < String > for Address {
139+ #[ inline]
140+ fn from_iter < I : IntoIterator < Item = String > > ( iter : I ) -> Self {
141+ Self ( iter. into_iter ( ) . collect ( ) )
142+ }
143+ }
144+
145+ impl std:: iter:: Extend < String > for Address {
146+ #[ inline]
147+ fn extend < T : IntoIterator < Item = String > > ( & mut self , iter : T ) {
148+ self . 0 . extend ( iter)
149+ }
150+ }
151+
152+ impl std:: iter:: IntoIterator for Address {
153+ type Item = String ;
154+
155+ type IntoIter = std:: collections:: vec_deque:: IntoIter < String > ;
156+
157+ #[ inline]
158+ fn into_iter ( self ) -> Self :: IntoIter {
159+ self . 0 . into_iter ( )
160+ }
161+ }
162+
163+ impl From < FieldRef > for Address {
164+ #[ inline]
165+ fn from ( field : FieldRef ) -> Self {
166+ field. into_iter ( ) . collect ( )
167+ }
168+ }
0 commit comments