little_exif/
util.rs

1// Copyright © 2024 Tobias J. Prisching <tobias.prisching@icloud.com> and CONTRIBUTORS
2// See https://github.com/TechnikTobi/little_exif#license for licensing details
3
4/// Inserts a slice into a vector at a given offset, shifting elements 
5/// starting at the offset towards the end.
6/// Returns 0 (zero) if the operation was successful, non-zero if the offset 
7/// is larger than the current length of the destination vector. In the latter 
8/// case, everything stays untouched.
9pub(crate) fn 
10insert_multiple_at<T>
11(
12    vec_dst: &mut Vec<T>,
13    offset:  usize,
14    vec_src: &mut Vec<T>,
15)
16-> usize
17where T: Copy 
18{
19    match (vec_dst.len(), vec_src.len()) 
20    {
21        (_, 0)           => 0,
22        (current_len, _) => {
23
24            // If this is true we return at this point as this would cause a
25            // "gap" between existing and new vector contents
26            if current_len < offset
27            {
28                return std::cmp::max(1, current_len);
29            }
30
31            // Reserve without over-allocation space needed for new elements
32            vec_dst.reserve_exact(vec_src.len());
33
34            let mut temp = vec_dst.split_off(offset);
35            vec_dst.append(vec_src);
36            vec_dst.append(&mut temp);
37
38            return 0;
39        },
40    }
41}
42
43/// Removes a section in the middle of a vector. The element at index `start` 
44/// is where the removal starts, up to the element prior to at index `end`
45/// The element originally positioned at `end` will survive. 
46pub(crate) fn
47range_remove<T>
48(
49    vec:   &mut Vec<T>,
50    start: usize,
51    end:   usize
52)
53where T: Copy
54{
55    // Invalid input, nothing to do here
56    if start > end { return; }
57
58    let old_vec_len = vec.len();
59
60    // Simply truncating is sufficient in this case
61    if end >= old_vec_len { vec.truncate(start); return; }
62
63    // Otherwise, move the elements starting at end over to the left
64    for (dst_offset, src_index) in (end..old_vec_len).enumerate()
65    {
66        vec[start + dst_offset] = vec[src_index];
67    }
68
69    // Resize the vector to cut off any residue from the shifting operations
70    let new_vec_len = old_vec_len - (end - start);
71    vec.truncate(new_vec_len);
72}
73
74/*
75/// Inserts a slice into a vector at a given offset, shifting elements 
76/// starting at the offset towards the end.
77/// Returns 0 (zero) if the operation was successful, non-zero if the offset 
78/// is larger than the current length of the destination vector. In the latter 
79/// case, everything stays untouched.
80pub(crate) fn insert_multiple_at<T>
81(
82    vec_dst: &mut Vec<T>, 
83    offset:  usize, 
84    vec_src: &mut [T]
85)
86-> usize
87where T: Copy 
88{
89    match (vec_dst.len(), vec_src.len()) 
90    {
91        (_, 0)           => 0,
92        (current_len, _) => {
93
94            // Elements that need to be moved to make way for the new ones
95            let move_count = current_len - offset;
96
97            // If this is less than 0 we return at this point as this would
98            // cause a "gap" between existing and new vector contents
99            // (move_count is usize and thus can't be less than 0)
100            if current_len < offset
101            {
102                return std::cmp::max(1, current_len);
103            }
104
105            // Reserve without over-allocation space needed for new elements
106            vec_dst.reserve_exact(vec_src.len());
107
108            unsafe
109            {
110                // Pointer to the first location where vec_src elements will
111                // be placed. 
112                // Called `src` at this stage as previously it has to serve
113                // as source for elements that require to be copied to the
114                // right to make way 
115                let src = vec_dst.as_mut_ptr().offset(offset as isize);
116
117                // Set the new length of the vector after the operation
118                vec_dst.set_len(current_len + vec_src.len());
119
120                // Check if there are any elements that require to be moved
121                if move_count > 0 
122                {
123                    let dst = src.offset(vec_src.len() as isize);
124                    std::ptr::copy(
125                        src,                                                    // Source pointer
126                        dst,                                                    // Destination pointer
127                        move_count                                              // How many elements to copy
128                    );
129                }
130
131                // Copy the new elements at the new "free" locations
132                // The previous source pointer `src` becomes the destination of
133                // the new elements to be inserted
134                // In contrast to the previous copy we can here be sure that
135                // the source and destination don't overlap
136                std::ptr::copy_nonoverlapping(
137                    vec_src.as_mut_ptr(),                                       // Source pointer
138                    src,                                                        // Destination pointer
139                    vec_src.len()                                               // How many elements to copy (here: ALL)
140                );
141            }
142
143            return 0;
144        },
145    }
146}
147*/