Merge pull request #3321 from gitbutlerapp/remove-line-file

remove linefile
This commit is contained in:
Josh Junon 2024-03-25 23:00:36 +01:00 committed by GitHub
commit 4163ad23ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 1 additions and 281 deletions

View File

@ -133,8 +133,6 @@ jobs:
- ''
- '*'
- []
- [git2]
- [mmap]
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/check-crate

61
Cargo.lock generated
View File

@ -1334,18 +1334,6 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "enum-as-inner"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a"
dependencies = [
"heck 0.4.1",
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
name = "enumflags2"
version = "0.7.8"
@ -1991,8 +1979,6 @@ dependencies = [
name = "gitbutler-changeset"
version = "0.0.0"
dependencies = [
"git2",
"mmap-rs",
"paste",
"thiserror",
]
@ -2863,15 +2849,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
[[package]]
name = "mach2"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8"
dependencies = [
"libc",
]
[[package]]
name = "malloc_buf"
version = "0.0.6"
@ -2986,23 +2963,6 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "mmap-rs"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86968d85441db75203c34deefd0c88032f275aaa85cee19a1dcfff6ae9df56da"
dependencies = [
"bitflags 1.3.2",
"combine",
"libc",
"mach2",
"nix 0.26.4",
"sysctl",
"thiserror",
"widestring",
"windows 0.48.0",
]
[[package]]
name = "native-tls"
version = "0.2.11"
@ -3065,7 +3025,6 @@ dependencies = [
"cfg-if",
"libc",
"memoffset 0.7.1",
"pin-utils",
]
[[package]]
@ -5263,20 +5222,6 @@ dependencies = [
"windows-sys 0.45.0",
]
[[package]]
name = "sysctl"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec7dddc5f0fee506baf8b9fdb989e242f17e4b11c61dfbb0635b705217199eea"
dependencies = [
"bitflags 2.4.0",
"byteorder",
"enum-as-inner",
"libc",
"thiserror",
"walkdir",
]
[[package]]
name = "sysinfo"
version = "0.30.7"
@ -6485,12 +6430,6 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
[[package]]
name = "widestring"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8"
[[package]]
name = "winapi"
version = "0.2.8"

View File

@ -3,15 +3,8 @@ name = "gitbutler-changeset"
version = "0.0.0"
edition = "2021"
[features]
default = ["git2", "mmap"]
git2 = ["dep:git2"]
mmap = ["dep:mmap-rs"]
[dependencies]
thiserror.workspace = true
git2 = { workspace = true, optional = true }
mmap-rs = { version = "0.6.1", optional = true }
[dev-dependencies]
paste = "1.0.14"

View File

@ -46,14 +46,7 @@
#![allow(clippy::doc_markdown, clippy::missing_errors_doc)]
#![feature(impl_trait_in_assoc_type, iter_map_windows, slice_as_chunks)]
mod linefile;
mod signature;
mod span;
#[cfg(feature = "mmap")]
pub use self::linefile::mmap::MmapLineFile;
pub use self::{
linefile::{memory::MemoryLineFile, CrlfBehavior, LineEndings, LineFile},
signature::Signature,
span::LineSpan,
};
pub use self::{signature::Signature, span::LineSpan};

View File

@ -1,69 +0,0 @@
use crate::LineSpan;
use std::fmt;
pub mod memory;
#[cfg(feature = "mmap")]
pub mod mmap;
/// A file, delimited by lines. The line ending is unspecified;
/// it is assumed the underlying implementation handles (and omits)
/// line endings for us.
///
/// All text is assumed to be UTF-8.
pub trait LineFile<'a> {
/// The type of iterator returned by [`LineFile::lines`] and [`LineFile::extract`].
type LineIterator: Iterator<Item = &'a str>;
/// Gets the line count of the file.
fn line_count(&self) -> usize;
/// Returns a slice of lines given the span.
///
/// # Panics
///
/// Panics if the span is out of bounds.
fn extract(&'a self, span: LineSpan) -> Self::LineIterator;
/// Returns an iterator over the all lines of the file.
fn lines(&'a self) -> Self::LineIterator {
self.extract(LineSpan::new(0, self.line_count() - 1))
}
/// Render the file to the given [`fmt::Write`]r.
/// Will append each line, including the last, with the line ending
/// specified by `line_endings`.
fn render<W: fmt::Write>(
&'a self,
writer: &mut W,
line_endings: LineEndings,
) -> Result<(), fmt::Error> {
for line in self.lines() {
writer.write_str(line)?;
match line_endings {
LineEndings::Unix => writer.write_char('\n')?,
LineEndings::Windows => writer.write_str("\r\n")?,
}
}
Ok(())
}
}
/// The behavior of CRLF (carriage return + line feed) characters
/// when splitting a file into lines.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CrlfBehavior {
/// Trims carriage returns (`\r`) from the end of lines.
Trim,
/// Keeps carriage returns (`\r`) at the end of lines.
Keep,
}
/// Which line ending to emit when rendering files to a [`fmt::Write`]r.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LineEndings {
/// Use Unix-style line endings (`\n`).
Unix,
/// Use Windows-style line endings (`\r\n`).
Windows,
}

View File

@ -1,47 +0,0 @@
#![allow(clippy::module_name_repetitions)]
use crate::{CrlfBehavior, LineFile, LineSpan};
/// A [`LineFile`] stored in memory.
pub struct MemoryLineFile {
lines: Vec<String>,
}
impl MemoryLineFile {
/// Creates a new [`MemoryLineFile`] from the given lines.
#[must_use]
pub fn new(lines: Vec<String>) -> Self {
Self { lines }
}
/// Creates a new [`MemoryLineFile`] from the given text,
/// with the given CRLF behavior.
#[must_use]
pub fn from_str(text: &str, crlf_behavior: CrlfBehavior) -> Self {
MemoryLineFile {
lines: text
.split('\n')
.map(|line| match crlf_behavior {
CrlfBehavior::Trim => line.trim_end_matches('\r').to_owned(),
CrlfBehavior::Keep => line.to_owned(),
})
.collect(),
}
}
}
impl<'a> LineFile<'a> for MemoryLineFile {
type LineIterator = impl Iterator<Item = &'a str>;
#[inline]
fn line_count(&self) -> usize {
self.lines.len()
}
#[must_use]
fn extract(&'a self, span: LineSpan) -> Self::LineIterator {
self.lines[span.start()..=span.end()]
.iter()
.map(AsRef::as_ref)
}
}

View File

@ -1,87 +0,0 @@
#![allow(clippy::module_name_repetitions)]
use crate::{CrlfBehavior, LineFile};
use mmap_rs::{Error, Mmap};
/// A [`LineFile`] created from a read-only memory-mapped file.
pub struct MmapLineFile {
mmap: Mmap,
line_slices: Vec<(usize, usize)>,
}
impl MmapLineFile {
/// Creates a new [`MmapLineFile`] from the given memory-mapped file.
///
/// Will attempt to make the Mmap read-only. Upon failure to do so,
/// returns both the original [`Mmap`] and the error.
///
/// # Panics
///
/// Panics if the document's contents are not valid UTF-8.
pub fn from_mmap(mmap: Mmap, crlf_behavior: CrlfBehavior) -> Result<Self, (Mmap, Error)> {
let mmap = mmap.make_read_only()?;
let mut line_slices = Vec::new();
// We check it here to avoid having to check it in the loop.
std::str::from_utf8(mmap.as_ref()).expect("mmap contents are not valid UTF-8");
MmapLineFile::init_lines(mmap.as_slice(), &mut line_slices, crlf_behavior);
Ok(Self { mmap, line_slices })
}
/// Creates a new [`MmapLineFile`] from the given file path.
/// **Unsafely** assumes the file is UTF-8 and will not attempt to convert it.
///
/// Will attempt to make the Mmap read-only. Upon failure to do so,
/// returns both the original [`Mmap`] and the error.
///
/// # Safety
///
/// This function is unsafe because it assumes the file is UTF-8. If it is not,
/// the behavior is undefined.
pub unsafe fn from_mmap_unsafe(
mmap: Mmap,
crlf_behavior: CrlfBehavior,
) -> Result<Self, (Mmap, Error)> {
let mmap = mmap.make_read_only()?;
let mut line_slices = Vec::new();
MmapLineFile::init_lines(mmap.as_slice(), &mut line_slices, crlf_behavior);
Ok(Self { mmap, line_slices })
}
fn init_lines(text: &[u8], lines: &mut Vec<(usize, usize)>, crlf_behavior: CrlfBehavior) {
text.iter()
.enumerate()
.fold((0, false), |(start, cr), (i, c)| {
if *c == b'\n' {
lines.push((
start,
i - usize::from(cr && crlf_behavior == CrlfBehavior::Trim),
));
(i + 1, false)
} else {
(start, *c == b'\r')
}
});
}
}
impl<'a> LineFile<'a> for MmapLineFile {
type LineIterator = impl Iterator<Item = &'a str>;
#[inline]
fn line_count(&self) -> usize {
self.line_slices.len()
}
fn extract(&'a self, span: crate::LineSpan) -> Self::LineIterator {
let mmap_ref = self.mmap.as_ref();
self.line_slices[span.start()..=span.end()]
.iter()
.map(|(start, end)| &mmap_ref[*start..=*end])
// The unsafe variant has been checked in the constructors.
// Either they called `from_mmap` and it was checked there,
// or they called `from_mmap_unsafe` and the caller assumes
// responsibility for the UTF-8 invariant.
.map(|bytes| unsafe { std::str::from_utf8_unchecked(bytes) })
}
}