@@ -36,112 +36,6 @@ pub struct Editor<'a> {
3636 tree_buf : Vec < u8 > ,
3737}
3838
39- /// The mode of items storable in a tree, similar to the file mode on a unix file system.
40- ///
41- /// We use the Git backing representation to avoid the need for allocations.
42- ///
43- /// Used in [`EntryRef`].
44- ///
45- /// Note that even though it can be created from any `u16`, it should be preferable to
46- /// create it by converting [`EntryKind`] into `EntryMode`.
47- #[ derive( Clone , Copy , PartialEq , Eq , Ord , PartialOrd , Hash ) ]
48- #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
49- pub struct EntryModeRef < ' a > {
50- pub ( crate ) mode : & ' a [ u8 ] ,
51- }
52-
53- impl std:: fmt:: Debug for EntryModeRef < ' _ > {
54- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
55- write ! (
56- f,
57- "EntryModeRef({})" ,
58- std:: str :: from_utf8( self . mode) . expect( "self.mode is valid UTF-8 by construction" )
59- )
60- }
61- }
62-
63- impl std:: fmt:: Octal for EntryModeRef < ' _ > {
64- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
65- write ! (
66- f,
67- "{}" ,
68- std:: str :: from_utf8( self . mode) . expect( "self.mode is valid UTF-8 by construction" )
69- )
70- }
71- }
72-
73- impl EntryModeRef < ' _ > {
74- /// Convert this instance into its own version, creating a copy of all data.
75- ///
76- /// This will temporarily allocate an extra copy in memory, so at worst three copies of the tree exist
77- /// at some intermediate point in time. Use [`Self::into_owned()`] to avoid this.
78- pub fn to_owned ( & self ) -> EntryMode {
79- ( * self ) . into_owned ( )
80- }
81-
82- /// Convert this instance into its own version, creating a copy of all data.
83- pub fn into_owned ( self ) -> EntryMode {
84- self . into ( )
85- }
86- }
87-
88- impl EntryModeRef < ' _ > {
89- /// Discretize the raw mode into an enum with well-known state while dropping unnecessary details.
90- pub const fn kind ( & self ) -> EntryKind {
91- if let Some ( value) = parse_git_mode ( self . mode ) {
92- parse_entry_kind_from_value ( value)
93- } else {
94- // Won't happen by construction.
95- // We swallow the error to allow this fn to be a `const fn`
96- EntryKind :: Commit
97- }
98- }
99-
100- /// Return true if this entry mode represents a Tree/directory
101- pub const fn is_tree ( & self ) -> bool {
102- matches ! ( self . kind( ) , EntryKind :: Tree )
103- }
104-
105- /// Return true if this entry mode represents the commit of a submodule.
106- pub const fn is_commit ( & self ) -> bool {
107- matches ! ( self . kind( ) , EntryKind :: Commit )
108- }
109-
110- /// Return true if this entry mode represents a symbolic link
111- pub const fn is_link ( & self ) -> bool {
112- matches ! ( self . kind( ) , EntryKind :: Link )
113- }
114-
115- /// Return true if this entry mode represents anything BUT Tree/directory
116- pub const fn is_no_tree ( & self ) -> bool {
117- !matches ! ( self . kind( ) , EntryKind :: Tree )
118- }
119-
120- /// Return true if the entry is any kind of blob.
121- pub const fn is_blob ( & self ) -> bool {
122- matches ! ( self . kind( ) , EntryKind :: Blob | EntryKind :: BlobExecutable )
123- }
124-
125- /// Return true if the entry is an executable blob.
126- pub const fn is_executable ( & self ) -> bool {
127- matches ! ( self . kind( ) , EntryKind :: BlobExecutable )
128- }
129-
130- /// Return true if the entry is any kind of blob or symlink.
131- pub const fn is_blob_or_symlink ( & self ) -> bool {
132- matches ! (
133- self . kind( ) ,
134- EntryKind :: Blob | EntryKind :: BlobExecutable | EntryKind :: Link
135- )
136- }
137-
138- /// Return the representation as used in the git internal format, which is octal and written
139- /// to the `backing` buffer. The respective sub-slice that was written to is returned.
140- pub fn as_bytes ( & self ) -> & ' _ BStr {
141- self . mode . into ( )
142- }
143- }
144-
14539/// Parse a valid git mode into a u16
14640/// A valid git mode can be represented by a set of 5-6 octal digits. The leftmost octal digit can
14741/// be at most one. These conditions guarantee that it can be represented as a `u16`, although that
@@ -220,22 +114,22 @@ impl TryFrom<u32> for tree::EntryMode {
220114///
221115/// Note that even though it can be created from any `u16`, it should be preferable to
222116/// create it by converting [`EntryKind`] into `EntryMode`.
223- #[ derive( Clone , PartialEq , Eq , Ord , PartialOrd , Hash ) ]
117+ #[ derive( Clone , Copy , PartialEq , Eq , Ord , PartialOrd , Hash ) ]
224118#[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
225119pub struct EntryMode {
226120 pub ( crate ) value : u16 ,
227- pub ( crate ) git_representation : BString ,
121+ pub ( crate ) git_representation : [ u8 ; 6 ] ,
228122}
229123
230124impl std:: fmt:: Debug for EntryMode {
231125 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
232- write ! ( f, "EntryMode(0o{})" , self . git_representation )
126+ write ! ( f, "EntryMode(0o{})" , self . as_bstr ( ) )
233127 }
234128}
235129
236130impl std:: fmt:: Octal for EntryMode {
237131 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
238- write ! ( f, "{}" , self . git_representation )
132+ write ! ( f, "{}" , self . as_bstr ( ) )
239133 }
240134}
241135
@@ -286,10 +180,8 @@ impl From<u16> for EntryKind {
286180
287181impl From < u16 > for EntryMode {
288182 fn from ( value : u16 ) -> Self {
289- Self {
290- value,
291- git_representation : format ! ( "{value:o}" ) . into ( ) ,
292- }
183+ let kind: EntryKind = value. into ( ) ;
184+ Self :: from ( kind)
293185 }
294186}
295187
@@ -301,23 +193,22 @@ impl From<EntryMode> for u16 {
301193
302194impl From < EntryMode > for EntryKind {
303195 fn from ( value : EntryMode ) -> Self {
304- EntryModeRef :: from ( & value) . kind ( )
196+ EntryMode :: from ( value) . kind ( )
305197 }
306198}
307199
308200/// Serialization
309201impl EntryKind {
310202 /// Return the representation as used in the git internal format.
311- pub fn as_octal_str ( & self ) -> & ' static BStr {
203+ pub fn as_octal_str ( & self ) -> & ' static [ u8 ] {
312204 use EntryKind :: * ;
313- let bytes : & [ u8 ] = match self {
205+ match self {
314206 Tree => b"40000" ,
315207 Blob => b"100644" ,
316208 BlobExecutable => b"100755" ,
317209 Link => b"120000" ,
318210 Commit => b"160000" ,
319- } ;
320- bytes. into ( )
211+ }
321212 }
322213 /// Return the representation as a human readable description
323214 pub fn as_descriptive_str ( & self ) -> & ' static str {
@@ -331,18 +222,13 @@ impl EntryKind {
331222 }
332223 }
333224}
334- impl From < EntryKind > for EntryModeRef < ' _ > {
335- fn from ( value : EntryKind ) -> Self {
336- EntryModeRef {
337- mode : value. as_octal_str ( ) ,
338- }
339- }
340- }
341225
342226impl From < EntryKind > for EntryMode {
343227 fn from ( value : EntryKind ) -> Self {
228+ let mut git_representation = [ b' ' ; 6 ] ;
229+ git_representation[ ..value. as_octal_str ( ) . len ( ) ] . copy_from_slice ( value. as_octal_str ( ) ) ;
344230 EntryMode {
345- git_representation : value . as_octal_str ( ) . to_owned ( ) ,
231+ git_representation,
346232 value : value as u16 ,
347233 }
348234 }
@@ -392,10 +278,25 @@ impl EntryMode {
392278 )
393279 }
394280
281+ /// How many bytes of the backing representation are significant?
282+ pub fn len ( & self ) -> usize {
283+ if let Some ( delim) = self . git_representation . iter ( ) . position ( |b| * b == b' ' ) {
284+ delim
285+ } else {
286+ self . git_representation . len ( )
287+ }
288+ }
289+
395290 /// Return the representation as used in the git internal format, which is octal and written
396291 /// to the `backing` buffer. The respective sub-slice that was written to is returned.
397- pub fn as_bytes ( & self ) -> & ' _ BStr {
398- self . git_representation . as_bstr ( )
292+ pub fn as_bytes ( & self ) -> & ' _ [ u8 ] {
293+ & self . git_representation [ ..self . len ( ) ]
294+ }
295+
296+ /// Return the representation as used in the git internal format, which is octal and written
297+ /// to the `backing` buffer. The respective sub-slice that was written to is returned.
298+ pub fn as_bstr ( & self ) -> & ' _ BStr {
299+ self . as_bytes ( ) . as_bstr ( )
399300 }
400301}
401302
@@ -419,7 +320,7 @@ impl TreeRef<'_> {
419320#[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
420321pub struct EntryRef < ' a > {
421322 /// The kind of object to which `oid` is pointing.
422- pub mode : tree:: EntryModeRef < ' a > ,
323+ pub mode : tree:: EntryMode ,
423324 /// The name of the file in the parent tree.
424325 pub filename : & ' a BStr ,
425326 /// The id of the object representing the entry.
@@ -470,14 +371,8 @@ impl Ord for Entry {
470371 let a = self ;
471372 let common = a. filename . len ( ) . min ( b. filename . len ( ) ) ;
472373 a. filename [ ..common] . cmp ( & b. filename [ ..common] ) . then_with ( || {
473- let a = a
474- . filename
475- . get ( common)
476- . or_else ( || EntryModeRef :: from ( & a. mode ) . is_tree ( ) . then_some ( & b'/' ) ) ;
477- let b = b
478- . filename
479- . get ( common)
480- . or_else ( || EntryModeRef :: from ( & b. mode ) . is_tree ( ) . then_some ( & b'/' ) ) ;
374+ let a = a. filename . get ( common) . or_else ( || a. mode . is_tree ( ) . then_some ( & b'/' ) ) ;
375+ let b = b. filename . get ( common) . or_else ( || b. mode . is_tree ( ) . then_some ( & b'/' ) ) ;
481376 a. cmp ( & b)
482377 } )
483378 }
0 commit comments