@@ -59,17 +59,19 @@ impl Pointer {
5959 pub fn new ( tokens : & [ impl AsRef < str > ] ) -> Self {
6060 let mut inner = String :: new ( ) ;
6161 for t in tokens. iter ( ) . map ( Token :: new) {
62- inner. push_str ( & prepend ( t. encoded ( ) ) ) ;
63- }
64- if inner. is_empty ( ) {
6562 inner. push ( '/' ) ;
63+ inner. push_str ( t. encoded ( ) ) ;
6664 }
6765 Pointer {
6866 inner,
6967 err : None ,
7068 count : tokens. len ( ) ,
7169 }
7270 }
71+ /// Extracts a string slice containing the entire encoded `Pointer`.
72+ pub fn as_str ( & self ) -> & str {
73+ & self . inner
74+ }
7375
7476 /// Returns `true` if the `Pointer` is valid. The only way an invalid
7577 /// `Pointer` can occur is through deserialization.
@@ -82,10 +84,6 @@ impl Pointer {
8284 /// Pushes a `Token` onto the front of this `Pointer`.
8385 pub fn push_front ( & mut self , token : Token ) {
8486 self . count += 1 ;
85- if self . inner == "/" {
86- self . inner . push_str ( token. encoded ( ) ) ;
87- return ;
88- }
8987 self . inner . insert ( 0 , '/' ) ;
9088 self . inner . insert_str ( 1 , token. encoded ( ) ) ;
9189 }
@@ -100,50 +98,73 @@ impl Pointer {
10098
10199 /// Removes and returns the last `Token` in the `Pointer` if it exists.
102100 pub fn pop_back ( & mut self ) -> Option < Token > {
103- if self . inner . len ( ) == 1 {
101+ if self . is_root ( ) {
104102 return None ;
105103 }
106104 if self . count > 0 {
107105 self . count -= 1 ;
108106 }
107+ self . inner [ 1 ..]
108+ . rsplit_once ( '/' )
109+ . map_or ( Some ( ( & self . inner [ 1 ..] , "" ) ) , Option :: Some )
110+ . map ( |( f, b) | ( f. to_owned ( ) , b. to_owned ( ) ) )
111+ . map ( |( front, back) | {
112+ if !front. is_empty ( ) {
113+ self . inner = String :: from ( "/" ) + & front;
114+ } else {
115+ self . inner = "" . to_owned ( ) ;
116+ }
117+ Token :: from_encoded ( back)
118+ } )
109119
110- self . rsplit_once ( ) . map ( |( front, back) | {
111- self . inner = prepend ( & front) ;
112- Token :: from_encoded ( back )
113- } )
120+ // self.rsplit_once().map(|(front, back)| {
121+ // self.inner = maybe_prepend_slash (&front);
122+
123+ // })
114124 }
115125 /// Removes and returns the first `Token` in the `Pointer` if it exists.
116126 pub fn pop_front ( & mut self ) -> Option < Token > {
117- if self . inner . len ( ) == 1 {
127+ if self . inner . is_empty ( ) {
118128 return None ;
119129 }
120130 if self . count > 0 {
121131 self . count -= 1 ;
122132 }
123133
124- self . split_once ( ) . map ( |( front, rest) | {
125- self . inner = prepend ( & rest) ;
126- front. into ( )
127- } )
134+ self . inner [ 1 ..]
135+ . split_once ( '/' )
136+ . map_or ( Some ( ( & self . inner [ 1 ..] , "" ) ) , Option :: Some )
137+ . map ( |( f, b) | ( f. to_owned ( ) , b. to_owned ( ) ) )
138+ . map ( |( front, back) | {
139+ if !back. is_empty ( ) {
140+ self . inner = String :: from ( "/" ) + & back;
141+ } else {
142+ self . inner = String :: new ( )
143+ }
144+ front. into ( )
145+ } )
128146 }
129147 /// Returns the number of tokens in the `Pointer`.
130148 pub fn count ( & self ) -> usize {
131149 self . count
132150 }
133- /// Returns `true` if the JSON Pointer equals `"/ "`.
151+ /// Returns `true` if the JSON Pointer equals `""`.
134152 pub fn is_root ( & self ) -> bool {
135- self . inner == "/"
153+ self . inner . is_empty ( )
136154 }
137155
138156 /// Returns the last `Token` in the `Pointer`.
139157 pub fn back ( & self ) -> Option < Token > {
140- self . rsplit_once ( ) . map ( |( front, last) | {
141- if last. is_empty ( ) {
142- Token :: from_encoded ( front)
143- } else {
144- Token :: from_encoded ( last)
145- }
146- } )
158+ self . inner [ 1 ..]
159+ . rsplit_once ( '/' )
160+ . map_or ( Some ( ( & self . inner [ 1 ..] , "" ) ) , Option :: Some )
161+ . map ( |( front, back) | {
162+ if !back. is_empty ( ) {
163+ Token :: from_encoded ( back)
164+ } else {
165+ Token :: from_encoded ( front)
166+ }
167+ } )
147168 }
148169 /// Returns the last token in the `Pointer`.
149170 ///
@@ -153,7 +174,13 @@ impl Pointer {
153174 }
154175 /// Returns the first `Token` in the `Pointer`.
155176 pub fn front ( & self ) -> Option < Token > {
156- self . split_once ( ) . map ( |( front, _) | front. into ( ) )
177+ if self . is_root ( ) {
178+ return None ;
179+ }
180+ self . inner [ 1 ..]
181+ . split_once ( '/' )
182+ . map_or ( Some ( ( & self . inner [ 1 ..] , "" ) ) , Option :: Some )
183+ . map ( |( front, _) | Token :: from_encoded ( front) )
157184 }
158185 /// Returns the first `Token` in the `Pointer`.
159186 ///
@@ -202,6 +229,13 @@ impl Pointer {
202229 index : usize ,
203230 token : Token ,
204231 ) -> Result < Option < Token > , ReplaceTokenError > {
232+ if self . is_root ( ) {
233+ return Err ( ReplaceTokenError {
234+ count : self . count ,
235+ index,
236+ pointer : self . clone ( ) ,
237+ } ) ;
238+ }
205239 let mut tokens = self . tokens ( ) . collect :: < Vec < _ > > ( ) ;
206240 if index > tokens. len ( ) {
207241 return Err ( ReplaceTokenError {
@@ -211,23 +245,21 @@ impl Pointer {
211245 } ) ;
212246 }
213247 let old = tokens. get ( index) . cloned ( ) ;
214-
215248 tokens[ index] = token;
216249
217- self . inner = prepend (
218- & tokens
250+ self . inner = String :: from ( "/" )
251+ + & tokens
219252 . iter ( )
220- . map ( |t| t . encoded ( ) )
253+ . map ( Token :: encoded)
221254 . collect :: < Vec < _ > > ( )
222- . join ( "/" ) ,
223- ) ;
255+ . join ( "/" ) ;
224256 Ok ( old)
225257 }
226258
227259 /// Clears the `Pointer`, setting it to root (`"/"`).
228260 pub fn clear ( & mut self ) {
229261 self . count = 0 ;
230- self . inner = prepend ( "" )
262+ self . inner = String :: from ( "" ) ;
231263 }
232264
233265 /// Returns an iterator of `Token`s in the `Pointer`.
@@ -772,33 +804,12 @@ impl Pointer {
772804 s. next ( ) ;
773805 s
774806 }
775- fn split_once ( & self ) -> Option < ( String , String ) > {
776- if self . is_root ( ) {
777- None
778- } else {
779- self . inner [ 1 ..]
780- . split_once ( '/' )
781- . map_or ( Some ( ( & self . inner [ 1 ..] , "" ) ) , Option :: Some )
782- . map ( |( f, b) | ( f. to_owned ( ) , b. to_owned ( ) ) )
783- }
784- }
785-
786- fn rsplit_once ( & self ) -> Option < ( String , String ) > {
787- if self . is_root ( ) {
788- None
789- } else {
790- self . inner [ 1 ..]
791- . rsplit_once ( '/' )
792- . map_or ( Some ( ( & self . inner [ 1 ..] , "" ) ) , Option :: Some )
793- . map ( |( f, b) | ( f. to_owned ( ) , b. to_owned ( ) ) )
794- }
795- }
796807}
797808
798809impl Default for Pointer {
799810 fn default ( ) -> Self {
800811 Self {
801- inner : "/" . to_owned ( ) ,
812+ inner : "" . to_string ( ) ,
802813 err : None ,
803814 count : 0 ,
804815 }
@@ -918,12 +929,12 @@ impl TryFrom<&str> for Pointer {
918929
919930fn validate_and_format ( value : & str ) -> Result < ( usize , String ) , MalformedPointerError > {
920931 let mut chars = value. chars ( ) ;
921- let mut next = chars . next ( ) ;
922- match next {
932+
933+ match chars . next ( ) {
923934 Some ( '#' ) => {
924- next = chars. next ( ) ;
935+ let next = chars. next ( ) ;
925936 if next. is_none ( ) {
926- return Ok ( ( 0 , "/" . into ( ) ) ) ;
937+ return Ok ( ( 0 , "" . to_string ( ) ) ) ;
927938 }
928939 if next != Some ( '/' ) {
929940 return Err ( MalformedPointerError :: NoLeadingSlash ( value. into ( ) ) ) ;
@@ -934,24 +945,27 @@ fn validate_and_format(value: &str) -> Result<(usize, String), MalformedPointerE
934945 return Err ( MalformedPointerError :: NoLeadingSlash ( value. into ( ) ) ) ;
935946 }
936947 None => {
937- return Ok ( ( 0 , "/" . into ( ) ) ) ;
948+ return Ok ( ( 0 , "" . to_string ( ) ) ) ;
938949 }
939950 }
940951 let mut res = String :: with_capacity ( value. len ( ) ) ;
941952 res. push ( '/' ) ;
942953 let mut count = 1 ; // accounting for the first slash
954+
943955 while let Some ( c) = chars. next ( ) {
944956 res. push ( c) ;
945- if c == '~' {
946- match chars. next ( ) {
957+ match c {
958+ '~' => match chars. next ( ) {
947959 Some ( '0' ) => res. push ( '0' ) ,
948960 Some ( '1' ) => res. push ( '1' ) ,
949961 _ => {
950962 return Err ( MalformedPointerError :: InvalidEncoding ( value. to_string ( ) ) ) ;
951963 }
964+ } ,
965+ '/' => {
966+ count += 1 ;
952967 }
953- } else if c == '/' {
954- count += 1 ;
968+ _ => { }
955969 }
956970 }
957971 Ok ( ( count, res) )
@@ -1006,7 +1020,7 @@ impl FromStr for Pointer {
10061020 }
10071021}
10081022
1009- fn prepend ( s : & str ) -> String {
1023+ fn prepend_slash ( s : & str ) -> String {
10101024 if !s. starts_with ( '/' ) {
10111025 "/" . to_string ( ) + s
10121026 } else {
0 commit comments