inverted_index_util/
entity_list.rs1use std::cmp::Ordering::{Equal, Greater, Less};
2use typenum::uint::Unsigned;
3
4pub fn insert_entity_mut<N>(entity_list: &mut Vec<u8>, entity: &[u8])
5where
6 N: Unsigned,
7{
8 let entity_len = N::to_usize();
9 assert_eq!(entity_len, entity.len());
10
11 let list_len = entity_list.len();
12
13 assert_eq!(list_len.checked_rem(entity_len), Some(0));
14 let mut size = list_len / entity_len;
15
16 if size == 0 {
17 entity_list.splice(0..0, entity.iter().copied());
18 return;
19 }
20
21 let mut base = 0usize;
22 while size > 1 {
23 let half = size / 2;
24 let mid = base + half;
25 let start = mid * entity_len;
26 let end = start + entity_len;
27 let cmp = entity_list[start..end].cmp(entity);
28 base = if cmp == Greater { base } else { mid };
29 size -= half;
30 }
31
32 let start = base * entity_len;
33 let end = start + entity_len;
34 let cmp = entity_list[start..end].cmp(entity);
35
36 let offset = match cmp {
37 Equal => return, Less => (base + 1) * entity_len,
39 Greater => base * entity_len,
40 };
41
42 entity_list.splice(offset..offset, entity.iter().copied());
43}
44
45pub enum ImmutResult {
46 Changed(Vec<u8>),
47 Unchanged,
48}
49pub fn insert_entity_immut<N>(entity_list: &[u8], entity: &[u8]) -> ImmutResult
50where
51 N: Unsigned,
52{
53 let entity_len = N::to_usize();
54 assert_eq!(entity_len, entity.len());
55
56 let list_len = entity_list.len();
57
58 assert_eq!(list_len.checked_rem(entity_len), Some(0));
59 let mut size = list_len / entity_len;
60
61 if size == 0 {
62 let mut entity_list = entity_list.to_vec();
63 entity_list.splice(0..0, entity.iter().copied());
64 return ImmutResult::Changed(entity_list);
65 }
66
67 let mut base = 0usize;
68 while size > 1 {
69 let half = size / 2;
70 let mid = base + half;
71 let start = mid * entity_len;
72 let end = start + entity_len;
73 let cmp = entity_list[start..end].cmp(entity);
74 base = if cmp == Greater { base } else { mid };
75 size -= half;
76 }
77
78 let start = base * entity_len;
79 let end = start + entity_len;
80 let cmp = entity_list[start..end].cmp(entity);
81
82 let offset = match cmp {
83 Equal => return ImmutResult::Unchanged, Less => (base + 1) * entity_len,
85 Greater => base * entity_len,
86 };
87
88 let mut entity_list = entity_list.to_vec();
89 entity_list.splice(offset..offset, entity.iter().copied());
90
91 ImmutResult::Changed(entity_list)
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97 use typenum::consts::{U16, U32};
98
99 #[test]
100 fn insert_document_mut_16() {
101 let mut entity_list: Vec<u8> = Vec::new();
102
103 insert_entity_mut::<U16>(&mut entity_list, b"aaaaaaaaaaaaaaaa");
104 insert_entity_mut::<U16>(&mut entity_list, b"cccccccccccccccc");
105 insert_entity_mut::<U16>(&mut entity_list, b"aaaaaaaaaaaaaaaa");
106 insert_entity_mut::<U16>(&mut entity_list, b"bbbbbbbbbbbbbbbb");
107
108 assert_eq!(&entity_list[..], &b"aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbcccccccccccccccc"[..]);
109 }
110 #[test]
111 fn insert_document_immut_16() {
112 let mut entity_list = Vec::new();
113
114 match insert_entity_immut::<U16>(&entity_list, b"aaaaaaaaaaaaaaaa") {
115 ImmutResult::Changed(l) => entity_list = l,
116 ImmutResult::Unchanged => {}
117 };
118 match insert_entity_immut::<U16>(&entity_list, b"cccccccccccccccc") {
119 ImmutResult::Changed(l) => entity_list = l,
120 ImmutResult::Unchanged => {}
121 };
122 match insert_entity_immut::<U16>(&entity_list, b"aaaaaaaaaaaaaaaa") {
123 ImmutResult::Changed(l) => entity_list = l,
124 ImmutResult::Unchanged => {}
125 };
126 match insert_entity_immut::<U16>(&entity_list, b"bbbbbbbbbbbbbbbb") {
127 ImmutResult::Changed(l) => entity_list = l,
128 ImmutResult::Unchanged => {}
129 };
130
131 assert_eq!(entity_list, &b"aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbcccccccccccccccc"[..]);
132 }
133
134 #[test]
135 fn insert_document_mut_32() {
136 let mut entity_list: Vec<u8> = Vec::new();
137
138 insert_entity_mut::<U32>(&mut entity_list, b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
139 insert_entity_mut::<U32>(&mut entity_list, b"cccccccccccccccccccccccccccccccc");
140 insert_entity_mut::<U32>(&mut entity_list, b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
141 insert_entity_mut::<U32>(&mut entity_list, b"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
142
143 assert_eq!(
144 &entity_list[..],
145 &b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc"[..]
146 );
147 }
148 #[test]
149 fn insert_document_immut_32() {
150 let mut entity_list = Vec::new();
151
152 match insert_entity_immut::<U32>(&entity_list, b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") {
153 ImmutResult::Changed(l) => entity_list = l,
154 ImmutResult::Unchanged => {}
155 };
156 match insert_entity_immut::<U32>(&entity_list, b"cccccccccccccccccccccccccccccccc") {
157 ImmutResult::Changed(l) => entity_list = l,
158 ImmutResult::Unchanged => {}
159 };
160 match insert_entity_immut::<U32>(&entity_list, b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") {
161 ImmutResult::Changed(l) => entity_list = l,
162 ImmutResult::Unchanged => {}
163 };
164 match insert_entity_immut::<U32>(&entity_list, b"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb") {
165 ImmutResult::Changed(l) => entity_list = l,
166 ImmutResult::Unchanged => {}
167 };
168
169 assert_eq!(
170 entity_list,
171 &b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc"[..]
172 );
173 }
174}