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*/