Skip to content
This repository has been archived by the owner on Mar 1, 2019. It is now read-only.

Commit

Permalink
Introduce enum distinguishing between USV and UTF-16 code points
Browse files Browse the repository at this point in the history
  • Loading branch information
Xanewok committed Nov 6, 2018
1 parent a3fb589 commit 3fde048
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 67 deletions.
6 changes: 2 additions & 4 deletions benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ extern crate rls_vfs;
extern crate test;

use rls_span::{Column, Position, Row, Span};
use rls_vfs::{Change, SpanAtom};
use rls_vfs::{Change, VfsSpan};
use std::fs;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -48,10 +48,8 @@ fn make_change_(path: &Path, start_line: usize, interval: usize) -> Change {
);
let buf = (0..LEN).map(|_| txt.to_owned() + "\n").collect::<String>();
Change::ReplaceText {
span: Span::from_positions(start, end, path),
len: None,
span: VfsSpan::from_usv(Span::from_positions(start, end, path), None),
text: buf,
atom: SpanAtom::UnicodeScalarValue,
}
}

Expand Down
80 changes: 49 additions & 31 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,50 @@ macro_rules! try_opt_loc {

pub struct Vfs<U = ()>(VfsInternal<RealFileLoader, U>);

type Span = span::Span<span::ZeroIndexed>;
/// Span of the text to be replaced defined in col/row terms.
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct SpanData {
/// Span of the text defined in col/row terms.
pub span: span::Span<span::ZeroIndexed>,
/// Length in chars of the text. If present,
/// used to calculate replacement range instead of
/// span's row_end/col_end fields. Needed for editors that
/// can't properly calculate the latter fields.
/// Span's row_start/col_start are still assumed valid.
pub len: Option<u64>,
}

#[derive(Debug)]
/// Defines a smallest text unit that `Span`s operate with.
pub enum SpanAtom {
/// `char` primitive
UnicodeScalarValue,
/// `u16` component in UTF-16 encoding
Utf16CodeUnit
/// Span of text that VFS can operate with.
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum VfsSpan {
/// Span with offsets based on unicode scalar values.
UnicodeScalarValue(SpanData),
/// Span with offsets based on UTF-16 code units.
Utf16CodeUnit(SpanData),
}

impl Default for SpanAtom {
fn default() -> Self {
SpanAtom::UnicodeScalarValue
impl VfsSpan {
pub fn from_usv(span: span::Span<span::ZeroIndexed>, len: Option<u64>) -> VfsSpan {
VfsSpan::UnicodeScalarValue(SpanData { span, len })
}

pub fn from_utf16(span: span::Span<span::ZeroIndexed>, len: Option<u64>) -> VfsSpan {
VfsSpan::Utf16CodeUnit(SpanData { span, len })
}

fn as_inner(&self) -> &SpanData {
match self {
VfsSpan::UnicodeScalarValue(span) => span,
VfsSpan::Utf16CodeUnit(span) => span,
}
}

pub fn span(&self) -> &span::Span<span::ZeroIndexed> {
&self.as_inner().span
}

pub fn len(&self) -> Option<u64> {
self.as_inner().len
}
}

Expand All @@ -51,19 +81,8 @@ pub enum Change {
AddFile { file: PathBuf, text: String },
/// Changes in-memory contents of the previously added file.
ReplaceText {
/// Span of the text to be replaced defined in col/row terms.
span: Span,
/// Length in chars of the text to be replaced. If present,
/// used to calculate replacement range instead of
/// span's row_end/col_end fields. Needed for editors that
/// can't properly calculate the latter fields.
/// Span's row_start/col_start are still assumed valid.
len: Option<u64>,
/// Specifies the atom units used by `span` and `len`.
/// For example, a buffer of "😢" has a column span of 0 to 1 and length
/// equal to 1 with `SpanAtom::UnicodeScalarValue` but a column span
/// of 0 to 2 and length equal to 2 with `SpanAtom::Utf16CodeUnit`.
atom: SpanAtom,
/// Span of the text to be replaced.
span: VfsSpan,
/// Text to replace specified text range with.
text: String,
},
Expand All @@ -73,7 +92,7 @@ impl Change {
fn file(&self) -> &Path {
match *self {
Change::AddFile { ref file, .. } => file.as_ref(),
Change::ReplaceText { ref span, .. } => span.file.as_ref(),
Change::ReplaceText { ref span, .. } => span.span().file.as_ref(),
}
}
}
Expand Down Expand Up @@ -681,21 +700,20 @@ impl TextFile {
let new_text = match **c {
Change::ReplaceText {
ref span,
ref len,
ref text,
ref atom,
} => {
let byte_in_str = match atom {
SpanAtom::UnicodeScalarValue => byte_in_str,
SpanAtom::Utf16CodeUnit => byte_in_str_utf16,
let byte_in_str = match span {
VfsSpan::UnicodeScalarValue(..) => byte_in_str,
VfsSpan::Utf16CodeUnit(..) => byte_in_str_utf16,
};
let (span, len) = (span.span(), span.len());

let range = {
let first_line = self.load_line(span.range.row_start)?;
let byte_start = self.line_indices[span.range.row_start.0 as usize]
+ byte_in_str(first_line, span.range.col_start)? as u32;

let byte_end = if let &Some(len) = len {
let byte_end = if let Some(len) = len {
// if `len` exists, the replaced portion of text
// is `len` chars starting from row_start/col_start.
byte_start + byte_in_str(
Expand Down
69 changes: 37 additions & 32 deletions src/test.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use std::path::{Path, PathBuf};

use span::{Column, Position, Row};
use span::{self, Column, Position, Row};

use super::{
make_line_indices, Change, Error, File, FileContents, FileKind, FileLoader, SpanAtom, TextFile,
VfsInternal,
make_line_indices, Change, Error, File, FileContents, FileKind, FileLoader, TextFile,
VfsInternal, VfsSpan
};
use Span;

type Span = span::Span<span::ZeroIndexed>;

struct MockFileLoader;

Expand Down Expand Up @@ -45,16 +46,17 @@ fn make_change(with_len: bool) -> Change {
(1, 4, None)
};
Change::ReplaceText {
span: Span::new(
Row::new_zero_indexed(1),
Row::new_zero_indexed(row_end),
Column::new_zero_indexed(1),
Column::new_zero_indexed(col_end),
"foo",
span: VfsSpan::from_usv(
Span::new(
Row::new_zero_indexed(1),
Row::new_zero_indexed(row_end),
Column::new_zero_indexed(1),
Column::new_zero_indexed(col_end),
"foo",
),
len,
),
len: len,
text: "foo".to_owned(),
atom: SpanAtom::UnicodeScalarValue,
}
}

Expand All @@ -67,16 +69,17 @@ fn make_change_2(with_len: bool) -> Change {
(3, 2, None)
};
Change::ReplaceText {
span: Span::new(
Row::new_zero_indexed(2),
Row::new_zero_indexed(row_end),
Column::new_zero_indexed(4),
Column::new_zero_indexed(col_end),
"foo",
span: VfsSpan::from_usv(
Span::new(
Row::new_zero_indexed(2),
Row::new_zero_indexed(row_end),
Column::new_zero_indexed(4),
Column::new_zero_indexed(col_end),
"foo",
),
len,
),
len: len,
text: "aye carumba".to_owned(),
atom: SpanAtom::UnicodeScalarValue,
}
}

Expand Down Expand Up @@ -319,14 +322,15 @@ fn test_wide_utf8() {
text: String::from("😢"),
},
Change::ReplaceText {
span: Span::from_positions(
Position::new(Row::new_zero_indexed(0), Column::new_zero_indexed(0)),
Position::new(Row::new_zero_indexed(0), Column::new_zero_indexed(1)),
"foo",
span: VfsSpan::from_usv(
Span::from_positions(
Position::new(Row::new_zero_indexed(0), Column::new_zero_indexed(0)),
Position::new(Row::new_zero_indexed(0), Column::new_zero_indexed(1)),
"foo",
),
Some(1),
),
len: Some(1),
text: "".into(),
atom: SpanAtom::UnicodeScalarValue,
},
];

Expand All @@ -347,14 +351,15 @@ fn test_wide_utf16() {
text: String::from("😢"),
},
Change::ReplaceText {
span: Span::from_positions(
Position::new(Row::new_zero_indexed(0), Column::new_zero_indexed(0)),
Position::new(Row::new_zero_indexed(0), Column::new_zero_indexed(2)),
"foo",
span: VfsSpan::from_utf16(
Span::from_positions(
Position::new(Row::new_zero_indexed(0), Column::new_zero_indexed(0)),
Position::new(Row::new_zero_indexed(0), Column::new_zero_indexed(2)),
"foo",
),
Some(2),
),
len: Some(2),
text: "".into(),
atom: SpanAtom::Utf16CodeUnit,
},
];

Expand Down

0 comments on commit 3fde048

Please sign in to comment.