add signature handling

This commit is contained in:
Josh Junon 2024-01-15 14:50:59 +01:00 committed by GitButler
parent 217b051b2b
commit 789325b191
15 changed files with 447 additions and 134 deletions

6
Cargo.lock generated
View File

@ -3337,6 +3337,12 @@ dependencies = [
"subtle",
]
[[package]]
name = "paste"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "pathdiff"
version = "0.2.1"

View File

@ -4,11 +4,16 @@ version = "0.0.0"
edition = "2021"
[features]
default = ["git2", "mmap"]
default = ["git2", "mmap", "serde"]
git2 = ["dep:git2"]
mmap = ["dep:mmap-rs"]
serde = ["dep:serde"]
[dependencies]
thiserror.workspace = true
serde = { workspace = true, optional = true }
git2 = { workspace = true, optional = true }
mmap-rs = { version = "0.6.0", optional = true }
[dev-dependencies]
paste = "1.0.14"

View File

@ -0,0 +1,8 @@
for i in 0..hashes.len() {
for j in i+1..hashes.len() {
- let (file, hash) = &hashes[i];
+ let (file1, hash1) = &hashes[i];
let (file2, hash2) = &hashes[j];
println!("Hamming distance between {} and {}: {}", file1, file2, hash1.distance(hash2));
}
}

View File

@ -0,0 +1,8 @@
for i in 0..hashes.len() {
for j in i+1..hashes.len() {
- let (file, hash) = &hashes[i];
+ let (first, first_hash) = &hashes[i];
let (file2, hash2) = &hashes[j];
println!("Hamming distance between {} and {}: {}", file1, file2, hash1.distance(hash2));
}
}

View File

@ -0,0 +1,8 @@
for file in &files {
println!("File: {} ({} bytes)", file.0, file.1.len());
}
let hasher: hamming_lsh::HammingHasher<B, H> = hamming_lsh::HammingHasher::new();
println!("Created hasher");

View File

@ -0,0 +1,12 @@
fn chunk_bytes<'a, const N: usize>(bytes: &'a [u8]) -> impl Iterator<Item = BitArray<N>> + 'a {
bytes
.chunks(N)
.map(|chunk| {
// Create a new byte array of size N and copy the chunk into it,
// padding with zeros if the chunk is shorter than N.
let mut padded_chunk = [0; N];
padded_chunk[..chunk.len()].copy_from_slice(chunk);
BitArray::new(padded_chunk)
})
}

View File

@ -0,0 +1,37 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut orci libero, tincidunt sed elit vel, gravida vehicula velit. Cras lacinia aliquam purus, eu vestibulum massa faucibus a. Curabitur ultrices molestie sapien, quis laoreet lacus facilisis ut. Donec sollicitudin vestibulum leo, at imperdiet leo porta venenatis. Proin suscipit, ipsum quis eleifend eleifend, ante eros egestas nisi, et pharetra nulla lacus eget nulla. Pellentesque tempus erat nec velit semper, id eleifend dui vulputate. Nullam enim sem, sollicitudin eget aliquet et, scelerisque ullamcorper magna. Donec tempus velit ut neque ullamcorper, ut facilisis neque laoreet. Nulla facilisi. Nam lorem purus, porttitor id efficitur in, consectetur at dui. Praesent orci eros, auctor id tellus vel, maximus pharetra nulla. Sed sit amet ullamcorper risus.
Ut non tellus luctus, faucibus risus a, faucibus leo. Ut sem tortor, placerat eget gravida ornare, convallis sit amet velit. Proin eu enim id nisl egestas rhoncus. Suspendisse porta vulputate tortor, in ultricies tellus sollicitudin in. Nunc sit amet mi in ante tincidunt hendrerit sit amet vitae augue. Phasellus dignissim mauris nec justo sodales consectetur sed eu lorem. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam lectus sapien, hendrerit sed rhoncus in, congue et eros. Integer ac mi eu dolor hendrerit dapibus in sit amet metus. Cras bibendum vestibulum dui at ultricies. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In aliquam velit a lobortis rhoncus. Nullam convallis gravida dui sed consequat. In a feugiat libero, vitae placerat justo. Suspendisse a euismod leo.
Morbi et porttitor lectus. Proin sed vestibulum lorem. Quisque id sem efficitur, maximus arcu et, gravida purus. Nullam ut ante eu arcu ultrices sollicitudin quis nec nisl. Nulla venenatis urna laoreet arcu tincidunt, sed maximus tellus vehicula. Quisque condimentum lectus vel ante hendrerit fringilla a sed turpis. Nam ut enim enim.
Duis dapibus blandit porttitor. Aliquam ac arcu interdum nibh eleifend dignissim sed ac elit. Phasellus sit amet bibendum purus, quis fermentum turpis. Nam eu ante metus. In consequat nisl ligula, eu pharetra ligula tempor eu. Interdum et malesuada fames ac ante ipsum primis in faucibus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vulputate metus lectus, eu sodales nulla maximus ac. Praesent luctus dictum mi. Etiam malesuada rhoncus vehicula. Phasellus aliquam feugiat sagittis. Donec sed auctor erat. Proin volutpat metus felis, id iaculis libero euismod ut. Suspendisse potenti. Aenean scelerisque nunc non rhoncus imperdiet. Quisque sit amet massa eu purus tristique interdum nec quis felis.
Aliquam erat volutpat. Maecenas accumsan massa id nisl facilisis vulputate. Nulla non sollicitudin neque. Aliquam sit amet ipsum nulla. Integer nec condimentum quam. Quisque sagittis dapibus turpis ac consequat. Nam magna tortor, aliquam vel rhoncus laoreet, dictum sed turpis. Suspendisse potenti. Aenean sit amet lectus felis. Sed laoreet tincidunt velit et bibendum. Fusce nec risus lacinia, fringilla nunc in, porta libero. Phasellus condimentum fermentum hendrerit. Fusce id lacus neque. Phasellus turpis quam, porta nec blandit et, posuere vel nibh.
Integer tempor leo sed mi elementum vehicula. Donec eu nisl semper nisi auctor tempor. Morbi purus lorem, rhoncus ac sem ultricies, sagittis accumsan elit. Fusce ligula sapien, gravida ut diam iaculis, rhoncus blandit tellus. Vivamus molestie congue ex ac vestibulum. Vestibulum varius dolor leo, nec auctor nunc mollis ut. Quisque dignissim urna nunc, at accumsan nunc efficitur id. Nullam convallis enim nisi, sed pharetra velit rutrum ac. Etiam aliquam diam eu ante congue rhoncus. Duis fermentum nibh vitae ante scelerisque, ut pretium libero pulvinar. Nulla erat felis, tincidunt eget imperdiet quis, malesuada ac lorem. Sed pellentesque imperdiet sem non condimentum. Integer iaculis erat et ipsum ultrices porttitor.
Aliquam euismod iaculis hendrerit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin consequat neque quis malesuada pretium. Vivamus gravida ex nec nunc lobortis, quis convallis nisi placerat. Nullam non tincidunt erat. Sed sed hendrerit magna. Curabitur porta nulla tortor, at pharetra est vulputate eu. Donec facilisis sem vitae vestibulum vulputate. Maecenas ornare venenatis magna, sit amet sodales felis posuere ac. Vestibulum ac massa dictum, finibus est a, congue velit. Ut ligula enim, ullamcorper id dolor non, congue dignissim dolor. Nulla ut lacus eu velit congue lacinia sit amet a velit.
Integer quis mauris vitae massa porttitor faucibus. Phasellus et congue turpis. In sit amet leo convallis enim tempus ullamcorper a venenatis velit. Ut sodales facilisis nisi nec dictum. Donec in nisi gravida, aliquet lacus vel, dictum risus. Curabitur sapien lectus, vestibulum nec commodo vitae, volutpat a neque. In maximus mi ac purus luctus mattis. Pellentesque rutrum sem vitae euismod venenatis. Nunc in augue risus. Phasellus finibus ipsum non nibh feugiat molestie. Curabitur nisl metus, tincidunt eget blandit sit amet, viverra at ante. Mauris sed sapien non purus feugiat efficitur. Pellentesque volutpat elementum diam, ut aliquet purus convallis sed.
Aenean libero velit, viverra in quam a, ullamcorper finibus quam. Morbi vitae massa eget mi faucibus blandit vitae at felis. Sed tempor ante vel augue blandit vulputate. Aliquam condimentum augue purus, non iaculis libero consectetur at. Pellentesque in ultricies enim. In hac habitasse platea dictumst. Suspendisse potenti. Suspendisse rhoncus elementum nibh, a luctus leo facilisis sit amet. Sed ac tellus pellentesque, porta urna eu, tempus enim. Proin tempor nisl dictum justo egestas faucibus.
Aliquam vulputate purus sed lacus faucibus, in blandit augue semper. In vehicula laoreet rutrum. Duis commodo mattis arcu ut vulputate. Maecenas dignissim sed enim auctor rhoncus. Sed porta, odio vitae rutrum rhoncus, leo lectus maximus lorem, a tincidunt erat mi quis urna. Maecenas vitae lacus tempus, luctus nibh in, fermentum risus. Maecenas et risus nibh. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
Sed aliquet ex mi, non malesuada libero sagittis nec. Morbi molestie nibh nec facilisis pharetra. Integer et accumsan ligula, vel ullamcorper metus. Donec id neque erat. Mauris ut ligula nec diam pharetra tristique. Fusce eget placerat dui. Nam suscipit, nulla non blandit eleifend, lorem lectus consequat eros, sit amet condimentum diam elit vel odio. Nam rhoncus aliquet dolor in fermentum. Sed faucibus magna consectetur condimentum malesuada. Morbi vel sem non justo interdum tincidunt. Quisque tellus dolor, pulvinar ac tellus eget, volutpat dictum justo.
Vivamus tempor vel tellus ac dapibus. Nullam sagittis orci vel luctus tempus. Cras lorem tellus, scelerisque non mollis sit amet, fringilla vitae risus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec varius pretium posuere. Aenean commodo porta ullamcorper. Cras rutrum ac nisl vel mattis. Integer vitae sem volutpat, porttitor lacus ultrices, laoreet tellus. Etiam vulputate odio quis finibus pulvinar. Mauris id nunc porta, consequat ante ac, varius dui. Proin fermentum a eros at fermentum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aenean sem turpis, volutpat sit amet vestibulum non, cursus vel justo. Nam congue sapien nisl, sed posuere diam vestibulum ac. In mauris erat, convallis ac bibendum sed, consectetur a sapien.
Aenean varius, tortor ac luctus posuere, quam diam elementum lorem, eu vulputate velit metus vitae est. In imperdiet augue et venenatis dictum. Phasellus nec dapibus ex. Praesent porta ultricies sem quis molestie. Ut interdum enim et mi tristique, sed vehicula augue volutpat. Cras magna felis, maximus quis rutrum ac, varius at turpis. Donec tempor, velit at consectetur porttitor, elit est suscipit mi, in porttitor urna metus quis lorem. Mauris auctor vitae elit eu volutpat. Vestibulum at vulputate velit. Curabitur lorem odio, convallis et tellus at, dapibus consectetur ante. Sed vitae felis in odio dapibus tempor. Duis hendrerit dignissim lacus eget blandit. Sed eu volutpat eros, in feugiat mauris.
Proin elit ante, imperdiet vel elit et, iaculis facilisis purus. Ut eros neque, pharetra nec efficitur a, eleifend ut massa. In facilisis quam at neque aliquam, et pharetra purus finibus. Morbi et maximus tortor. Suspendisse nec enim sed ipsum semper lobortis. Nulla facilisi. Donec tempus dolor et feugiat volutpat. Nunc eget laoreet nisi. Aliquam dapibus ultricies ipsum, ut congue sem pellentesque vitae. In venenatis mauris risus, a elementum justo lobortis posuere. Sed facilisis vulputate lacus, sed laoreet mi. Praesent pretium enim ut efficitur tempor.
Etiam tempus finibus libero, at fermentum ipsum iaculis a. Sed consequat lacus dui, ac pulvinar enim placerat id. Nullam eu commodo felis. Cras vel nisi non lorem dapibus varius. Aliquam erat volutpat. Pellentesque a est nec turpis volutpat viverra. Phasellus tempus, diam ullamcorper varius viverra, nunc nibh fermentum justo, in pulvinar dolor nulla id mi. Nullam eget elementum sapien. Nam bibendum ac nisl eget ultrices. Etiam a accumsan nulla. Proin in tristique nulla, et feugiat tortor. Ut a justo ac tortor aliquam facilisis non eu quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nullam non viverra purus. Cras diam enim, venenatis vel risus nec, commodo imperdiet ligula.
Maecenas mattis quam non sapien venenatis, at congue massa sodales. Nullam sit amet arcu non quam tincidunt convallis id at ante. Aliquam commodo massa quis orci maximus, ut feugiat est congue. Nam vitae commodo nisi, quis feugiat massa. Proin vitae nibh nisl. Maecenas id enim nisi. Vivamus vel iaculis leo, non pretium dui. Mauris porttitor imperdiet lacus.
Quisque gravida sapien at ante gravida tempor. Proin consequat eros eu nibh suscipit, eu iaculis ipsum rhoncus. Sed at ipsum sed elit placerat egestas. Praesent dapibus tortor sed diam malesuada vehicula. Sed maximus orci semper, semper leo eget, suscipit elit. Phasellus odio lacus, maximus ac aliquam at, finibus ac velit. Quisque orci lacus, luctus ut nibh in, suscipit dignissim ipsum.
Vivamus et ex diam. Aliquam laoreet aliquet nibh quis faucibus. Curabitur congue molestie faucibus. Fusce a cursus risus. Mauris tincidunt dolor turpis, quis aliquet tellus commodo nec. Proin eu pharetra purus. Proin sed metus vitae purus tincidunt auctor nec vitae purus. Vivamus venenatis ut mi id viverra. Donec eleifend neque a diam posuere imperdiet. Praesent pellentesque risus at convallis feugiat. Aenean feugiat erat vel tellus finibus commodo. Donec blandit nec ante in ornare.
Aliquam dui enim, accumsan id magna vitae, dignissim luctus libero. Pellentesque porttitor ipsum ac est porttitor vehicula sed ac justo. Fusce gravida ultricies commodo. Donec a vulputate ex. Proin tempus purus et pretium maximus. Proin nec aliquam odio. Maecenas venenatis, sem eu mollis consectetur, justo dui viverra risus, fermentum pulvinar leo orci non est. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis ac rutrum orci.

View File

@ -0,0 +1,37 @@
Ut non tellus luctus, faucibus risus a, faucibus leo. Ut sem tortor, placerat eget gravida ornare, convallis sit amet velit. Proin eu enim id nisl egestas rhoncus. Suspendisse porta vulputate tortor, in ultricies tellus sollicitudin in. Nunc sit amet mi in ante tincidunt hendrerit sit amet vitae augue. Phasellus dignissim mauris nec justo sodales consectetur sed eu lorem. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam lectus sapien, hendrerit sed rhoncus in, congue et eros. Integer ac mi eu dolor hendrerit dapibus in sit amet metus. Cras bibendum vestibulum dui at ultricies. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In aliquam velit a lobortis rhoncus. Nullam convallis gravida dui sed consequat. In a feugiat libero, vitae placerat justo. Suspendisse a euismod leo.
Morbi et porttitor lectus. Proin sed vestibulum lorem. Quisque id sem efficitur, maximus arcu et, gravida purus. Nullam ut ante eu arcu ultrices sollicitudin quis nec nisl. Nulla venenatis urna laoreet arcu tincidunt, sed maximus tellus vehicula. Quisque condimentum lectus vel ante hendrerit fringilla a sed turpis. Nam ut enim enim.
Duis dapibus blandit porttitor. Aliquam ac arcu interdum nibh eleifend dignissim sed ac elit. Phasellus sit amet bibendum purus, quis fermentum turpis. Nam eu ante metus. In consequat nisl ligula, eu pharetra ligula tempor eu. Interdum et malesuada fames ac ante ipsum primis in faucibus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vulputate metus lectus, eu sodales nulla maximus ac. Praesent luctus dictum mi. Etiam malesuada rhoncus vehicula. Phasellus aliquam feugiat sagittis. Donec sed auctor erat. Proin volutpat metus felis, id iaculis libero euismod ut. Suspendisse potenti. Aenean scelerisque nunc non rhoncus imperdiet. Quisque sit amet massa eu purus tristique interdum nec quis felis.
Aliquam erat volutpat. Maecenas accumsan massa id nisl facilisis vulputate. Nulla non sollicitudin neque. Aliquam sit amet ipsum nulla. Integer nec condimentum quam. Quisque sagittis dapibus turpis ac consequat. Nam magna tortor, aliquam vel rhoncus laoreet, dictum sed turpis. Suspendisse potenti. Aenean sit amet lectus felis. Sed laoreet tincidunt velit et bibendum. Fusce nec risus lacinia, fringilla nunc in, porta libero. Phasellus condimentum fermentum hendrerit. Fusce id lacus neque. Phasellus turpis quam, porta nec blandit et, posuere vel nibh.
Integer tempor leo sed mi elementum vehicula. Donec eu nisl semper nisi auctor tempor. Morbi purus lorem, rhoncus ac sem ultricies, sagittis accumsan elit. Fusce ligula sapien, gravida ut diam iaculis, rhoncus blandit tellus. Vivamus molestie congue ex ac vestibulum. Vestibulum varius dolor leo, nec auctor nunc mollis ut. Quisque dignissim urna nunc, at accumsan nunc efficitur id. Nullam convallis enim nisi, sed pharetra velit rutrum ac. Etiam aliquam diam eu ante congue rhoncus. Duis fermentum nibh vitae ante scelerisque, ut pretium libero pulvinar. Nulla erat felis, tincidunt eget imperdiet quis, malesuada ac lorem. Sed pellentesque imperdiet sem non condimentum. Integer iaculis erat et ipsum ultrices porttitor.
Aliquam euismod iaculis hendrerit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin consequat neque quis malesuada pretium. Vivamus gravida ex nec nunc lobortis, quis convallis nisi placerat. Nullam non tincidunt erat. Sed sed hendrerit magna. Curabitur porta nulla tortor, at pharetra est vulputate eu. Donec facilisis sem vitae vestibulum vulputate. Maecenas ornare venenatis magna, sit amet sodales felis posuere ac. Vestibulum ac massa dictum, finibus est a, congue velit. Ut ligula enim, ullamcorper id dolor non, congue dignissim dolor. Nulla ut lacus eu velit congue lacinia sit amet a velit.
Integer quis mauris vitae massa porttitor faucibus. Phasellus et congue turpis. In sit amet leo convallis enim tempus ullamcorper a venenatis velit. Ut sodales facilisis nisi nec dictum. Donec in nisi gravida, aliquet lacus vel, dictum risus. Curabitur sapien lectus, vestibulum nec commodo vitae, volutpat a neque. In maximus mi ac purus luctus mattis. Pellentesque rutrum sem vitae euismod venenatis. Nunc in augue risus. Phasellus finibus ipsum non nibh feugiat molestie. Curabitur nisl metus, tincidunt eget blandit sit amet, viverra at ante. Mauris sed sapien non purus feugiat efficitur. Pellentesque volutpat elementum diam, ut aliquet purus convallis sed.
Aenean libero velit, viverra in quam a, ullamcorper finibus quam. Morbi vitae massa eget mi faucibus blandit vitae at felis. Sed tempor ante vel augue blandit vulputate. Aliquam condimentum augue purus, non iaculis libero consectetur at. Pellentesque in ultricies enim. In hac habitasse platea dictumst. Suspendisse potenti. Suspendisse rhoncus elementum nibh, a luctus leo facilisis sit amet. Sed ac tellus pellentesque, porta urna eu, tempus enim. Proin tempor nisl dictum justo egestas faucibus.
Aliquam vulputate purus sed lacus faucibus, in blandit augue semper. In vehicula laoreet rutrum. Duis commodo mattis arcu ut vulputate. Maecenas dignissim sed enim auctor rhoncus. Sed porta, odio vitae rutrum rhoncus, leo lectus maximus lorem, a tincidunt erat mi quis urna. Maecenas vitae lacus tempus, luctus nibh in, fermentum risus. Maecenas et risus nibh. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
Sed aliquet ex mi, non malesuada libero sagittis nec. Morbi molestie nibh nec facilisis pharetra. Integer et accumsan ligula, vel ullamcorper metus. Donec id neque erat. Mauris ut ligula nec diam pharetra tristique. Fusce eget placerat dui. Nam suscipit, nulla non blandit eleifend, lorem lectus consequat eros, sit amet condimentum diam elit vel odio. Nam rhoncus aliquet dolor in fermentum. Sed faucibus magna consectetur condimentum malesuada. Morbi vel sem non justo interdum tincidunt. Quisque tellus dolor, pulvinar ac tellus eget, volutpat dictum justo.
Vivamus tempor vel tellus ac dapibus. Nullam sagittis orci vel luctus tempus. Cras lorem tellus, scelerisque non mollis sit amet, fringilla vitae risus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec varius pretium posuere. Aenean commodo porta ullamcorper. Cras rutrum ac nisl vel mattis. Integer vitae sem volutpat, porttitor lacus ultrices, laoreet tellus. Etiam vulputate odio quis finibus pulvinar. Mauris id nunc porta, consequat ante ac, varius dui. Proin fermentum a eros at fermentum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aenean sem turpis, volutpat sit amet vestibulum non, cursus vel justo. Nam congue sapien nisl, sed posuere diam vestibulum ac. In mauris erat, convallis ac bibendum sed, consectetur a sapien.
Aenean varius, tortor ac luctus posuere, quam diam elementum lorem, eu vulputate velit metus vitae est. In imperdiet augue et venenatis dictum. Phasellus nec dapibus ex. Praesent porta ultricies sem quis molestie. Ut interdum enim et mi tristique, sed vehicula augue volutpat. Cras magna felis, maximus quis rutrum ac, varius at turpis. Donec tempor, velit at consectetur porttitor, elit est suscipit mi, in porttitor urna metus quis lorem. Mauris auctor vitae elit eu volutpat. Vestibulum at vulputate velit. Curabitur lorem odio, convallis et tellus at, dapibus consectetur ante. Sed vitae felis in odio dapibus tempor. Duis hendrerit dignissim lacus eget blandit. Sed eu volutpat eros, in feugiat mauris.
Proin elit ante, imperdiet vel elit et, iaculis facilisis purus. Ut eros neque, pharetra nec efficitur a, eleifend ut massa. In facilisis quam at neque aliquam, et pharetra purus finibus. Morbi et maximus tortor. Suspendisse nec enim sed ipsum semper lobortis. Nulla facilisi. Donec tempus dolor et feugiat volutpat. Nunc eget laoreet nisi. Aliquam dapibus ultricies ipsum, ut congue sem pellentesque vitae. In venenatis mauris risus, a elementum justo lobortis posuere. Sed facilisis vulputate lacus, sed laoreet mi. Praesent pretium enim ut efficitur tempor.
Etiam tempus finibus libero, at fermentum ipsum iaculis a. Sed consequat lacus dui, ac pulvinar enim placerat id. Nullam eu commodo felis. Cras vel nisi non lorem dapibus varius. Aliquam erat volutpat. Pellentesque a est nec turpis volutpat viverra. Phasellus tempus, diam ullamcorper varius viverra, nunc nibh fermentum justo, in pulvinar dolor nulla id mi. Nullam eget elementum sapien. Nam bibendum ac nisl eget ultrices. Etiam a accumsan nulla. Proin in tristique nulla, et feugiat tortor. Ut a justo ac tortor aliquam facilisis non eu quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nullam non viverra purus. Cras diam enim, venenatis vel risus nec, commodo imperdiet ligula.
Maecenas mattis quam non sapien venenatis, at congue massa sodales. Nullam sit amet arcu non quam tincidunt convallis id at ante. Aliquam commodo massa quis orci maximus, ut feugiat est congue. Nam vitae commodo nisi, quis feugiat massa. Proin vitae nibh nisl. Maecenas id enim nisi. Vivamus vel iaculis leo, non pretium dui. Mauris porttitor imperdiet lacus.
Quisque gravida sapien at ante gravida tempor. Proin consequat eros eu nibh suscipit, eu iaculis ipsum rhoncus. Sed at ipsum sed elit placerat egestas. Praesent dapibus tortor sed diam malesuada vehicula. Sed maximus orci semper, semper leo eget, suscipit elit. Phasellus odio lacus, maximus ac aliquam at, finibus ac velit. Quisque orci lacus, luctus ut nibh in, suscipit dignissim ipsum.
Vivamus et ex diam. Aliquam laoreet aliquet nibh quis faucibus. Curabitur congue molestie faucibus. Fusce a cursus risus. Mauris tincidunt dolor turpis, quis aliquet tellus commodo nec. Proin eu pharetra purus. Proin sed metus vitae purus tincidunt auctor nec vitae purus. Vivamus venenatis ut mi id viverra. Donec eleifend neque a diam posuere imperdiet. Praesent pellentesque risus at convallis feugiat. Aenean feugiat erat vel tellus finibus commodo. Donec blandit nec ante in ornare.
Aliquam dui enim, accumsan id magna vitae, dignissim luctus libero. Pellentesque porttitor ipsum ac est porttitor vehicula sed ac justo. Fusce gravida ultricies commodo. Donec a vulputate ex. Proin tempus purus et pretium maximus. Proin nec aliquam odio. Maecenas venenatis, sem eu mollis consectetur, justo dui viverra risus, fermentum pulvinar leo orci non est. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis ac rutrum orci.
Sed eu vehicula orci. Suspendisse convallis lectus justo, ac euismod justo sollicitudin non. Duis sodales eleifend neque ac sagittis. Donec non enim vulputate, auctor turpis eget, mattis sem. Aliquam pulvinar metus non posuere vestibulum. Mauris tristique, sem nec accumsan vulputate, ipsum urna imperdiet ante, quis hendrerit lorem sem sit amet enim. Nunc vel purus ut arcu lobortis imperdiet sed eu ipsum. Morbi aliquet purus vitae purus convallis vestibulum. Nullam et malesuada velit. Aenean tellus nisi, rutrum vitae augue ut, fermentum vestibulum quam. Morbi cursus neque a mi dictum pulvinar. Mauris a vulputate risus, sit amet lobortis ex. Cras sagittis ex sed nunc mattis, sit amet malesuada arcu dignissim.

View File

@ -0,0 +1,2 @@
This is a test
of your soundsystem

View File

@ -0,0 +1,2 @@
This is a test
of your pound system

View File

@ -0,0 +1,2 @@
This is entirely different text. There should be no similarities
between them.

View File

@ -5,13 +5,14 @@ use crate::Hunk;
/// file.
#[derive(Debug, Clone, Default)]
pub struct Changeset {
// NOTE: Must be sorted at all times; the implementation assumes this!
// NOTE: Inserts must perform sorted inserts based on source line number.
hunks: Vec<Hunk>,
}
/// Denotes that a hunk could not be added to a changeset
/// due to a conflict in the source range.
///
/// This is technically an [`std::error::Error`] type but is used in some
/// non-`Err` contexts.
#[derive(Debug, thiserror::Error)]
#[error("hunk conflicts with existing hunk (new hunk: {:?}, existing hunk: {:?})", .new.source_span(), .existing.source_span())]
pub struct HunkConflict {
@ -22,140 +23,33 @@ pub struct HunkConflict {
}
impl Changeset {
/// Attempts to add the given hunk to the changeset.
/// Errors if there's a conflict.
pub fn try_add(&mut self, hunk: Hunk) -> Result<(), HunkConflict> {
// Find the index of the first hunk that starts after the given hunk.
// We do this with a binary search based on the hunk source range's start.
let insert_index = match self
.hunks
.binary_search_by_key(&hunk.source_span().start(), |h| h.source_span().start())
{
Ok(index) => index,
Err(index) => index,
};
// Check the hunk before the insert index, if there is one.
// If it conflicts, error.
if insert_index > 0 {
if let Some(existing) = self.hunks.get(insert_index - 1) {
if existing.source_span().intersects(&hunk.source_span()) {
return Err(HunkConflict {
new: hunk,
existing: existing.clone(),
});
}
}
}
// Check the hunk after the insert index, if there is one.
// If it conflicts, error.
if let Some(existing) = self.hunks.get(insert_index) {
if existing.source_span().intersects(&hunk.source_span()) {
return Err(HunkConflict {
new: hunk,
existing: existing.clone(),
});
}
}
// No conflicts, insert the hunk.
self.hunks.insert(insert_index, hunk);
Ok(())
}
/// Returns an iterator over all hunks.
pub fn hunks(&self) -> impl Iterator<Item = &Hunk> {
/// Returns an iterator over the hunks in the changeset.
#[inline]
pub fn iter(&self) -> impl Iterator<Item = &Hunk> {
self.hunks.iter()
}
/// Returns a mutable iterator over the hunks in the changeset.
#[inline]
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Hunk> {
self.hunks.iter_mut()
}
fn sort(&mut self) {
self.hunks.sort_by_key(|hunk| hunk.source_span().start());
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::LineSpan;
#[test]
fn test_add() {
let mut changeset = Changeset::default();
// Insert hunks that don't conflict.
changeset
.try_add(Hunk::new(LineSpan::new(0, 0), "Hello, world!".to_string()))
.unwrap();
changeset
.try_add(Hunk::new(LineSpan::new(2, 2), "Hello, world!".to_string()))
.unwrap();
changeset
.try_add(Hunk::new(LineSpan::new(4, 4), "Hello, world!".to_string()))
.unwrap();
changeset
.try_add(Hunk::new(LineSpan::new(1, 1), "Hello, world!".to_string()))
.unwrap();
// Insert a hunk that conflicts with the first hunk.
assert!(matches!(
changeset.try_add(Hunk::new(LineSpan::new(0, 0), "Hello, world!".to_string())),
Err(HunkConflict { .. })
));
// Insert a hunk that conflicts with the second hunk.
assert!(matches!(
changeset.try_add(Hunk::new(LineSpan::new(2, 3), "Hello, world!".to_string())),
Err(HunkConflict { .. })
));
// Insert a hunk that conflicts with the third hunk.
assert!(matches!(
changeset.try_add(Hunk::new(LineSpan::new(3, 4), "Hello, world!".to_string())),
Err(HunkConflict { .. })
));
// Insert a hunk that conflicts with the first and second hunks.
assert!(matches!(
changeset.try_add(Hunk::new(LineSpan::new(0, 2), "Hello, world!".to_string())),
Err(HunkConflict { .. })
));
// Insert a hunk that conflicts with the second and third hunks.
assert!(matches!(
changeset.try_add(Hunk::new(LineSpan::new(2, 4), "Hello, world!".to_string())),
Err(HunkConflict { .. })
));
// Insert a hunk that conflicts with the first and third hunks.
assert!(matches!(
changeset.try_add(Hunk::new(LineSpan::new(0, 4), "Hello, world!".to_string())),
Err(HunkConflict { .. })
));
// Insert a hunk that conflicts with all hunks.
assert!(matches!(
changeset.try_add(Hunk::new(
LineSpan::new(0, 4),
"Hello, world!\nHello, world!\nHello, world!\nHello, world!".to_string()
)),
Err(HunkConflict { .. })
));
// Insert a few more valid hunks, some of which are in the middle of the changeset.
changeset
.try_add(Hunk::new(LineSpan::new(7, 9), "Hello, world!".to_string()))
.unwrap();
changeset
.try_add(Hunk::new(LineSpan::new(3, 3), "Hello, world!".to_string()))
.unwrap();
changeset
.try_add(Hunk::new(LineSpan::new(5, 6), "Hello, world!".to_string()))
.unwrap();
// Assert the hunks are sorted by their start line.
let mut hunks = changeset.hunks().peekable();
while let Some(hunk) = hunks.next() {
if let Some(next) = hunks.peek() {
assert!(hunk.source_span().start() < next.source_span().start());
impl Extend<Hunk> for Changeset {
fn extend<T: IntoIterator<Item = Hunk>>(&mut self, iter: T) {
self.hunks.extend(iter);
}
}
impl FromIterator<Hunk> for Changeset {
fn from_iter<T: IntoIterator<Item = Hunk>>(iter: T) -> Self {
Self {
hunks: Vec::from_iter(iter),
}
}
}

View File

@ -0,0 +1,3 @@
use crate::Hunk;
pub struct Diff {}

View File

@ -43,11 +43,13 @@
//! [GitButler organization](https://github.com/gitbutlerapp)
//! or the [GitButler website](https://gitbutler.com).
#![deny(missing_docs)]
#![feature(impl_trait_in_assoc_type)]
#![feature(impl_trait_in_assoc_type, iter_map_windows, slice_as_chunks)]
mod changeset;
mod diff;
mod hunk;
mod linefile;
mod signature;
mod span;
#[cfg(feature = "mmap")]
@ -56,5 +58,6 @@ pub use self::{
changeset::{Changeset, HunkConflict},
hunk::Hunk,
linefile::{memory::MemoryLineFile, CrlfBehavior, LineEndings, LineFile},
signature::Signature,
span::LineSpan,
};

View File

@ -0,0 +1,286 @@
const BITS: usize = 3;
const SHIFT: usize = 8 - BITS;
const SIG_ENTRIES: usize = (1 << BITS) * (1 << BITS);
const SIG_BYTES: usize = SIG_ENTRIES * ::core::mem::size_of::<SigBucket>();
const TOTAL_BYTES: usize = SIG_BYTES + 4 + 1; // we encode a 4-byte length at the beginning, along with a version byte
// NOTE: This is not efficient if `SigBucket` is 1 byte (u8).
// NOTE: If `SigBucket` is changed to a u8, then the implementation
// NOTE: *should* be updated to eschew the byte conversion and use
// NOTE: slices directly.
type SigBucket = u16;
/// Similarity signatures are fixed-width bigram histograms
/// from the Sorenson-Dice coefficient algorithm. They act
/// as fixed-length fingerprints for a file's contents,
/// usable to check similarity between two hunks, using the
/// fingerprint of the old hunk and the string contents
/// of a new hunk.
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Signature([u8; TOTAL_BYTES]);
impl Signature {
/// Creates a new signature from a byte array.
#[inline]
pub fn new(bytes: [u8; TOTAL_BYTES]) -> Self {
Self(bytes)
}
/// Returns the similarity signature as a byte array.
///
/// **NOTE:** Do not inspect the contents of this array,
/// or assume anything about its contents. It is an
/// implementation detail and may change at any time.
#[inline]
pub fn as_bytes(&self) -> &[u8; TOTAL_BYTES] {
&self.0
}
/// Scores this signature against a string.
/// Values are between 0.0 and 1.0, with 1.0 being
/// a perfect match.
///
/// Typically, values below 0.95 are pretty indicative
/// of unrelated hunks.
///
/// # Panics
///
/// Will panic if the signature has an unsupported version
/// byte.
///
/// # Security
///
/// This function is not fixed-time, and may leak information
/// about the signature or the original file contents.
///
/// Do not use for any security-related purposes.
pub fn score_str<S: AsRef<str>>(&self, s: S) -> f64 {
if self.0[0] != 0 {
panic!("unsupported signature version");
}
let original_length = u32::from_le_bytes(self.0[1..5].try_into().unwrap());
let s = s.as_ref();
let s_s: String = s.chars().filter(|&x| !char::is_whitespace(x)).collect();
let s = s_s.as_bytes();
if original_length < 2 || s.len() < 2 {
return 0.0;
}
let mut intersection_size = 0usize;
let mut wb = self.bucket_iter().collect::<Vec<_>>();
for (b1, b2) in bigrams(s) {
let b1 = b1 >> SHIFT;
let b2 = b2 >> SHIFT;
let ix = ((b1 as usize) << BITS) | (b2 as usize);
if wb[ix] > 0 {
wb[ix] = wb[ix].saturating_sub(1);
intersection_size += 1;
}
}
(2 * intersection_size) as f64 / (original_length as usize + s.len() - 2) as f64
}
fn bucket_iter(&self) -> impl Iterator<Item = SigBucket> + '_ {
unsafe {
self.0[(TOTAL_BYTES - SIG_BYTES)..]
.as_chunks_unchecked::<{ ::core::mem::size_of::<SigBucket>() }>()
.iter()
.map(|ch: &[u8; ::core::mem::size_of::<SigBucket>()]| SigBucket::from_le_bytes(*ch))
}
}
}
impl<S: AsRef<str>> From<S> for Signature {
#[inline]
fn from(s: S) -> Self {
let s = s.as_ref();
let a_s: String = s.chars().filter(|&x| !char::is_whitespace(x)).collect();
let a = a_s.as_bytes();
let a_len: u32 = a
.len()
.try_into()
.expect("strings with a byte-length above u32::MAX are not supported");
let mut a_res = [0; TOTAL_BYTES];
a_res[0] = 0; // version byte
a_res[1..5].copy_from_slice(&a_len.to_le_bytes()); // length
if a_len >= 2 {
let mut a_bigrams = [0 as SigBucket; SIG_ENTRIES];
for (b1, b2) in bigrams(a) {
let b1 = b1 >> SHIFT;
let b2 = b2 >> SHIFT;
let encoded_bigram = ((b1 as usize) << BITS) | (b2 as usize);
a_bigrams[encoded_bigram] = a_bigrams[encoded_bigram].saturating_add(1);
}
// NOTE: This is not efficient if `SigBucket` is 1 byte (u8).
let mut offset = TOTAL_BYTES - SIG_BYTES;
for bucket in a_bigrams {
let start = offset;
let end = start + ::core::mem::size_of::<SigBucket>();
a_res[start..end].copy_from_slice(&bucket.to_le_bytes());
offset = end;
}
}
Self(a_res)
}
}
#[inline]
fn bigrams(s: &[u8]) -> impl Iterator<Item = (u8, u8)> + '_ {
s.iter().copied().zip(s.iter().skip(1).copied())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn score_signature() {
let sig = Signature::from("hello world");
macro_rules! assert_score {
($s:expr, $e:expr) => {
if (sig.score_str($s) - $e).abs() >= 0.1 {
panic!(
"expected score of {} for string {:?}, got {}",
$e,
$s,
sig.score_str($s)
);
}
};
}
// NOTE: The scores here are not exact, but are close enough
// to be useful for testing purposes, hence why some have the same
// "score" but different strings.
assert_score!("hello world", 1.0);
assert_score!("hello world!", 0.95);
assert_score!("hello world!!", 0.9);
assert_score!("hello world!!!", 0.85);
assert_score!("hello world!!!!", 0.8);
assert_score!("hello world!!!!!", 0.75);
assert_score!("hello world!!!!!!", 0.7);
assert_score!("hello world!!!!!!!", 0.65);
assert_score!("hello world!!!!!!!!", 0.62);
assert_score!("hello world!!!!!!!!!", 0.6);
assert_score!("hello world!!!!!!!!!!", 0.55);
}
#[test]
fn score_ignores_whitespace() {
let sig = Signature::from("hello world");
macro_rules! assert_score {
($s:expr, $e:expr) => {
if (sig.score_str($s) - $e).abs() >= 0.1 {
panic!(
"expected score of {} for string {:?}, got {}",
$e,
$s,
sig.score_str($s)
);
}
};
}
assert_score!("hello world", 1.0);
assert_score!("hello world ", 1.0);
assert_score!("hello\nworld ", 1.0);
assert_score!("hello\n\tworld ", 1.0);
assert_score!("\t\t hel lo\n\two rld \t\t", 1.0);
}
const TEXT1: &str = include_str!("../fixture/text1.txt");
const TEXT2: &str = include_str!("../fixture/text2.txt");
const TEXT3: &str = include_str!("../fixture/text3.txt");
const CODE1: &str = include_str!("../fixture/code1.txt");
const CODE2: &str = include_str!("../fixture/code2.txt");
const CODE3: &str = include_str!("../fixture/code3.txt");
const CODE4: &str = include_str!("../fixture/code4.txt");
const LARGE1: &str = include_str!("../fixture/large1.txt");
const LARGE2: &str = include_str!("../fixture/large2.txt");
macro_rules! real_test {
($a: ident, $b: ident, are_similar) => {
paste::paste! {
#[test]
#[allow(non_snake_case)]
fn [<test_ $a _ $b _are_similar>]() {
let a = Signature::from($a);
let b = Signature::from($b);
assert!(a.score_str($b) >= 0.95);
assert!(b.score_str($a) >= 0.95);
}
}
};
($a: ident, $b: ident, are_not_similar) => {
paste::paste! {
#[test]
#[allow(non_snake_case)]
fn [<test_ $a _ $b _are_not_similar>]() {
let a = Signature::from($a);
let b = Signature::from($b);
assert!(a.score_str($b) < 0.95);
assert!(b.score_str($a) < 0.95);
}
}
};
}
// Only similar pairs:
// - TEXT1, TEXT2
// - CODE1, CODE2
// - LARGE1, LARGE2
real_test!(TEXT1, TEXT2, are_similar);
real_test!(CODE1, CODE2, are_similar);
real_test!(LARGE1, LARGE2, are_similar);
// Check all other combos
real_test!(TEXT1, TEXT3, are_not_similar);
real_test!(TEXT1, CODE1, are_not_similar);
real_test!(TEXT1, CODE2, are_not_similar);
real_test!(TEXT1, CODE3, are_not_similar);
real_test!(TEXT1, CODE4, are_not_similar);
real_test!(TEXT1, LARGE1, are_not_similar);
real_test!(TEXT1, LARGE2, are_not_similar);
real_test!(TEXT2, TEXT3, are_not_similar);
real_test!(TEXT2, CODE1, are_not_similar);
real_test!(TEXT2, CODE2, are_not_similar);
real_test!(TEXT2, CODE3, are_not_similar);
real_test!(TEXT2, CODE4, are_not_similar);
real_test!(TEXT2, LARGE1, are_not_similar);
real_test!(TEXT2, LARGE2, are_not_similar);
real_test!(TEXT3, CODE1, are_not_similar);
real_test!(TEXT3, CODE2, are_not_similar);
real_test!(TEXT3, CODE3, are_not_similar);
real_test!(TEXT3, CODE4, are_not_similar);
real_test!(TEXT3, LARGE1, are_not_similar);
real_test!(TEXT3, LARGE2, are_not_similar);
real_test!(CODE1, CODE3, are_not_similar);
real_test!(CODE1, CODE4, are_not_similar);
real_test!(CODE1, LARGE1, are_not_similar);
real_test!(CODE1, LARGE2, are_not_similar);
real_test!(CODE2, CODE3, are_not_similar);
real_test!(CODE2, CODE4, are_not_similar);
real_test!(CODE2, LARGE1, are_not_similar);
real_test!(CODE2, LARGE2, are_not_similar);
real_test!(CODE3, CODE4, are_not_similar);
real_test!(CODE3, LARGE1, are_not_similar);
real_test!(CODE3, LARGE2, are_not_similar);
real_test!(CODE4, LARGE1, are_not_similar);
real_test!(CODE4, LARGE2, are_not_similar);
}