Skip to content

Commit

Permalink
Merge pull request #118 from TheSignPainter98/context/rc-file-contents
Browse files Browse the repository at this point in the history
Use `Rc<str>` for file contents
  • Loading branch information
TheSignPainter98 authored Jul 4, 2023
2 parents 1706471 + 8c85ae5 commit 3e4ff74
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 1 deletion.
157 changes: 157 additions & 0 deletions crates/emblem_core/src/context/file_content.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
use std::{
borrow::Borrow,
fmt::Display,
ops::{Bound, Range, RangeBounds},
rc::Rc,
};

pub trait FileSlice: AsRef<str> {
fn slice<R: RangeBounds<usize>>(&self, index: R) -> FileContentSlice;
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FileContent {
inner: Rc<str>,
}

impl FileContent {
pub(crate) fn new(contents: &str) -> Self {
Self {
inner: contents.into(),
}
}
}

impl Default for FileContent {
fn default() -> Self {
Self::new("")
}
}

impl FileSlice for FileContent {
fn slice<R: RangeBounds<usize>>(&self, index: R) -> FileContentSlice {
let start = match index.start_bound() {
Bound::Included(i) => *i,
Bound::Excluded(_) => panic!("internal error: excluded left lower bound"),
Bound::Unbounded => 0,
};
let end = match index.end_bound() {
Bound::Included(i) => *i + 1,
Bound::Excluded(i) => *i,
Bound::Unbounded => self.as_ref().len(),
};
FileContentSlice {
raw: self.clone(),
range: start..end,
}
}
}

impl AsRef<str> for FileContent {
fn as_ref(&self) -> &str {
self.inner.as_ref()
}
}

impl Borrow<str> for FileContent {
fn borrow(&self) -> &str {
self.inner.borrow()
}
}

impl PartialEq<&str> for FileContent {
fn eq(&self, other: &&str) -> bool {
self.inner.as_ref() == *other
}
}

impl PartialEq<FileContent> for &str {
fn eq(&self, other: &FileContent) -> bool {
*self == other.inner.as_ref()
}
}

impl PartialEq<&str> for &FileContent {
fn eq(&self, other: &&str) -> bool {
self.inner.as_ref() == *other
}
}

impl PartialEq<&FileContent> for &str {
fn eq(&self, other: &&FileContent) -> bool {
*self == other.inner.as_ref()
}
}

impl Display for FileContent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.inner.fmt(f)
}
}

#[derive(Clone, Debug)]
pub struct FileContentSlice {
raw: FileContent,
range: Range<usize>,
}

impl FileSlice for FileContentSlice {
fn slice<R: RangeBounds<usize>>(&self, index: R) -> FileContentSlice {
let start = self.range.start
+ match index.start_bound() {
Bound::Included(i) => *i,
Bound::Excluded(_) => panic!("internal error: excluded left lower bound"),
Bound::Unbounded => 0,
};
let end = self.range.end
+ match index.end_bound() {
Bound::Included(i) => *i + 1,
Bound::Excluded(i) => *i,
Bound::Unbounded => self.as_ref().len(),
};
Self {
raw: self.raw.clone(),
range: start..end,
}
}
}

impl AsRef<str> for FileContentSlice {
fn as_ref(&self) -> &str {
&self.raw.as_ref()[self.range.clone()]
}
}

impl Display for FileContentSlice {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.as_ref().fmt(f)
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn slice_unbounded() {
let original = "hello big world";
let content = FileContent::new(original);
assert_eq!(original, content.slice(..).as_ref());
}

#[test]
fn slice_exclusive() {
let original = "hello big world";
let content = FileContent::new(original);
let range = 1..10;
assert_eq!(&original[range.clone()], content.slice(range).as_ref());
}

#[test]
fn slice_inclusive() {
let original = "hello big world";
let content = FileContent::new(original);
let range = 1..=10;
assert_eq!(&original[range.clone()], content.slice(range).as_ref());
}
}
1 change: 1 addition & 0 deletions crates/emblem_core/src/context/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub(crate) mod file_content;
pub(crate) mod file_name;
mod module;
mod resource_limit;
Expand Down
6 changes: 5 additions & 1 deletion crates/emblem_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ pub use crate::{
},
Builder,
},
context::{file_name::FileName, Context, ResourceLimit, SandboxLevel},
context::{
file_content::{FileContent, FileContentSlice},
file_name::FileName,
Context, ResourceLimit, SandboxLevel,
},
explain::Explainer,
extensions::ExtensionState,
lint::Linter,
Expand Down

0 comments on commit 3e4ff74

Please sign in to comment.