diff --git a/Cargo.toml b/Cargo.toml index 461b57c..f7ee203 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,13 +13,11 @@ exclude = [".github/", "bors.toml", "rustfmt.toml"] members = ["xtask"] [dependencies] -rustc-hash = "2.1.1" +rustc-hash = { version = "2.1.1", default-features = false } hashbrown = { version = "0.15.2", features = [ "inline-more", "raw-entry", ], default-features = false } -text-size = "1.1.1" -countme = "3.0.1" serde = { version = "1.0.218", optional = true, default-features = false } @@ -27,4 +25,5 @@ serde = { version = "1.0.218", optional = true, default-features = false } m_lexer = "0.0.4" [features] -serde1 = ["serde", "text-size/serde"] +std = ["rustc-hash/std"] +serde1 = ["dep:serde"] diff --git a/src/api.rs b/src/api.rs index 3a83daf..b477490 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,12 +1,13 @@ -use std::{borrow::Cow, fmt, iter, marker::PhantomData, ops::Range}; +use alloc::borrow::Cow; +use core::{fmt, hash::Hash, iter, marker::PhantomData, ops::Range}; use crate::{ Direction, GreenNode, GreenNodeData, GreenToken, NodeOrToken, SyntaxKind, SyntaxText, TextRange, TextSize, TokenAtOffset, WalkEvent, cursor, green::GreenTokenData, }; -pub trait Language: Sized + Copy + fmt::Debug + Eq + Ord + std::hash::Hash { - type Kind: Sized + Copy + fmt::Debug + Eq + Ord + std::hash::Hash; +pub trait Language: Sized + Copy + fmt::Debug + Eq + Ord + Hash { + type Kind: Sized + Copy + fmt::Debug + Eq + Ord + Hash; fn kind_from_raw(raw: SyntaxKind) -> Self::Kind; fn kind_to_raw(kind: Self::Kind) -> SyntaxKind; @@ -68,7 +69,7 @@ impl fmt::Debug for SyntaxToken { let text = self.text(); for idx in 21..25 { if text.is_char_boundary(idx) { - let text = format!("{} ...", &text[..idx]); + let text = alloc::format!("{} ...", &text[..idx]); return write!(f, " {:?}", text); } } diff --git a/src/arc.rs b/src/arc.rs index fa3774f..7dcfc8a 100644 --- a/src/arc.rs +++ b/src/arc.rs @@ -1,6 +1,7 @@ //! Vendored and stripped down version of triomphe -use std::{ - alloc::{self, Layout}, +use crate::alloc::alloc::{self, Layout}; +use crate::alloc::boxed::Box; +use core::{ cmp::Ordering, hash::{Hash, Hasher}, marker::PhantomData, @@ -86,7 +87,7 @@ impl Arc { /// allocation #[inline] pub(crate) fn ptr_eq(this: &Self, other: &Self) -> bool { - std::ptr::addr_eq(this.ptr(), other.ptr()) + ptr::addr_eq(this.ptr(), other.ptr()) } pub(crate) fn ptr(&self) -> *mut ArcInner { @@ -120,7 +121,7 @@ impl Clone for Arc { // We abort because such a program is incredibly degenerate, and we // don't care to support it. if old_size > MAX_REFCOUNT { - std::process::abort(); + panic!("Arc reference count overflow"); } unsafe { Arc { p: ptr::NonNull::new_unchecked(self.ptr()), phantom: PhantomData } } diff --git a/src/ast.rs b/src/ast.rs index 292dba9..c2699c0 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -13,7 +13,7 @@ //! We also provide an [`AstNode`] trait for typed AST wrapper APIs over rowan //! nodes. -use std::{ +use core::{ fmt, hash::{Hash, Hasher}, iter::successors, diff --git a/src/countme.rs b/src/countme.rs new file mode 100644 index 0000000..0fe40ca --- /dev/null +++ b/src/countme.rs @@ -0,0 +1,13 @@ +use core::marker::PhantomData; + +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub(crate) struct Count { + marker: PhantomData, +} + +impl Count { + #[inline] + pub(crate) const fn new() -> Self { + Self { marker: PhantomData } + } +} diff --git a/src/cow_mut.rs b/src/cow_mut.rs index 418d7ee..b36edd5 100644 --- a/src/cow_mut.rs +++ b/src/cow_mut.rs @@ -1,10 +1,12 @@ +use core::ops::{Deref, DerefMut}; + #[derive(Debug)] pub(crate) enum CowMut<'a, T> { Owned(T), Borrowed(&'a mut T), } -impl std::ops::Deref for CowMut<'_, T> { +impl Deref for CowMut<'_, T> { type Target = T; fn deref(&self) -> &T { match self { @@ -14,7 +16,7 @@ impl std::ops::Deref for CowMut<'_, T> { } } -impl std::ops::DerefMut for CowMut<'_, T> { +impl DerefMut for CowMut<'_, T> { fn deref_mut(&mut self) -> &mut T { match self { CowMut::Owned(it) => it, diff --git a/src/cursor.rs b/src/cursor.rs index 0ea88ac..28636e0 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -81,8 +81,12 @@ // when the tree is mutable. // - TBD -use std::{ - borrow::Cow, +use alloc::{ + borrow::{Cow, ToOwned}, + boxed::Box, + string::ToString, +}; +use core::{ cell::Cell, fmt, hash::{Hash, Hasher}, @@ -92,11 +96,10 @@ use std::{ ptr, slice, }; -use countme::Count; - use crate::{ Direction, GreenNode, GreenToken, NodeOrToken, SyntaxText, TextRange, TextSize, TokenAtOffset, WalkEvent, + countme::Count, green::{GreenChild, GreenElementRef, GreenNodeData, GreenTokenData, SyntaxKind}, sll, utility_types::Delta, @@ -285,7 +288,7 @@ impl NodeData { fn inc_rc(&self) { let rc = match self.rc.get().checked_add(1) { Some(it) => it, - None => std::process::abort(), + None => panic!("reference count overflow"), }; self.rc.set(rc) } @@ -327,7 +330,7 @@ impl NodeData { } } #[inline] - fn green_siblings(&self) -> slice::Iter { + fn green_siblings(&self) -> slice::Iter<'_, GreenChild> { match &self.parent().map(|it| &it.green) { Some(Green::Node { ptr }) => unsafe { &*ptr.get().as_ptr() }.children().raw, Some(Green::Token { .. }) => { @@ -607,7 +610,7 @@ impl SyntaxNode { assert!(self.can_take_ptr()); let ret = self.ptr; // don't change the refcount when self gets dropped - std::mem::forget(self); + mem::forget(self); ret } @@ -1000,7 +1003,7 @@ impl SyntaxToken { assert!(self.can_take_ptr()); let ret = self.ptr; // don't change the refcount when self gets dropped - std::mem::forget(self); + mem::forget(self); ret } @@ -1055,7 +1058,7 @@ impl SyntaxToken { #[inline] pub fn ancestors(&self) -> impl Iterator + use<> { - std::iter::successors(self.parent(), SyntaxNode::parent) + iter::successors(self.parent(), SyntaxNode::parent) } pub fn next_sibling_or_token(&self) -> Option { diff --git a/src/green.rs b/src/green.rs index e2b5b4a..a18db07 100644 --- a/src/green.rs +++ b/src/green.rs @@ -33,10 +33,10 @@ mod tests { #[test] fn test_size_of() { - use std::mem::size_of; + use core::mem::size_of; - eprintln!("GreenNode {}", size_of::()); - eprintln!("GreenToken {}", size_of::()); - eprintln!("GreenElement {}", size_of::()); + std::eprintln!("GreenNode {}", size_of::()); + std::eprintln!("GreenToken {}", size_of::()); + std::eprintln!("GreenElement {}", size_of::()); } } diff --git a/src/green/builder.rs b/src/green/builder.rs index a8becad..e985cde 100644 --- a/src/green/builder.rs +++ b/src/green/builder.rs @@ -1,4 +1,5 @@ -use std::num::NonZeroUsize; +use alloc::vec::Vec; +use core::num::NonZeroUsize; use crate::{ NodeOrToken, diff --git a/src/green/element.rs b/src/green/element.rs index 2945157..9cb23f0 100644 --- a/src/green/element.rs +++ b/src/green/element.rs @@ -1,4 +1,4 @@ -use std::borrow::Cow; +use alloc::borrow::{Cow, ToOwned}; use crate::{ GreenNodeData, NodeOrToken, TextSize, diff --git a/src/green/node.rs b/src/green/node.rs index d056abb..462ee01 100644 --- a/src/green/node.rs +++ b/src/green/node.rs @@ -1,16 +1,19 @@ -use std::{ - borrow::{Borrow, Cow}, +use alloc::{ + borrow::{Cow, ToOwned}, + vec::Vec, +}; +use core::{ + borrow::Borrow, fmt, iter::{self, FusedIterator}, mem::{self, ManuallyDrop}, ops, ptr, slice, }; -use countme::Count; - use crate::{ GreenToken, NodeOrToken, TextRange, TextSize, arc::{Arc, HeaderSlice, ThinArc}, + countme::Count, green::{GreenElement, GreenElementRef, SyntaxKind}, }; @@ -247,7 +250,7 @@ impl GreenNode { impl GreenChild { #[inline] - pub(crate) fn as_ref(&self) -> GreenElementRef { + pub(crate) fn as_ref(&self) -> GreenElementRef<'_> { match self { GreenChild::Node { node, .. } => NodeOrToken::Node(node), GreenChild::Token { token, .. } => NodeOrToken::Token(token), @@ -361,7 +364,7 @@ mod test { #[cfg(target_pointer_width = "64")] fn check_green_child_size() { use super::GreenChild; - use std::mem; + use core::mem; assert_eq!(mem::size_of::(), mem::size_of::() * 2); } diff --git a/src/green/node_cache.rs b/src/green/node_cache.rs index 89740bf..9caf8be 100644 --- a/src/green/node_cache.rs +++ b/src/green/node_cache.rs @@ -1,6 +1,7 @@ +use alloc::vec::Vec; +use core::hash::{BuildHasherDefault, Hash, Hasher}; use hashbrown::hash_map::RawEntryMut; use rustc_hash::FxHasher; -use std::hash::{BuildHasherDefault, Hash, Hasher}; use crate::{ GreenNode, GreenNodeData, GreenToken, GreenTokenData, NodeOrToken, SyntaxKind, diff --git a/src/green/token.rs b/src/green/token.rs index 9e6a1f0..333ad67 100644 --- a/src/green/token.rs +++ b/src/green/token.rs @@ -1,15 +1,15 @@ -use std::{ +use alloc::borrow::ToOwned; +use core::{ borrow::Borrow, fmt, mem::{self, ManuallyDrop}, ops, ptr, }; -use countme::Count; - use crate::{ TextSize, arc::{Arc, HeaderSlice, ThinArc}, + countme::Count, green::SyntaxKind, }; @@ -96,7 +96,7 @@ impl GreenTokenData { /// Text of this Token. #[inline] pub fn text(&self) -> &str { - unsafe { std::str::from_utf8_unchecked(self.data.slice()) } + unsafe { core::str::from_utf8_unchecked(self.data.slice()) } } /// Returns the length of the text covered by this token. diff --git a/src/lib.rs b/src/lib.rs index bb8f30d..4f30b0e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ //! A generic library for lossless syntax trees. //! See `examples/s_expressions.rs` for a tutorial. +#![no_std] #![forbid( // missing_debug_implementations, unconditional_recursion, @@ -8,13 +9,19 @@ )] #![deny(unsafe_code)] +extern crate alloc; +#[cfg(test)] +extern crate std; + #[allow(unsafe_code)] mod green; #[allow(unsafe_code)] pub mod cursor; pub mod api; +mod countme; mod syntax_text; +mod text_size; mod utility_types; mod cow_mut; @@ -26,7 +33,7 @@ mod arc; mod serde_impls; pub mod ast; -pub use text_size::{TextLen, TextRange, TextSize}; +pub use crate::text_size::{TextLen, TextRange, TextSize}; pub use crate::{ api::{ diff --git a/src/serde_impls.rs b/src/serde_impls.rs index 529303b..eaf71f9 100644 --- a/src/serde_impls.rs +++ b/src/serde_impls.rs @@ -1,5 +1,5 @@ +use core::fmt; use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer}; -use std::fmt; use crate::{ NodeOrToken, diff --git a/src/sll.rs b/src/sll.rs index 6947660..97028a5 100644 --- a/src/sll.rs +++ b/src/sll.rs @@ -1,6 +1,6 @@ //! Sorted Linked List -use std::{cell::Cell, cmp::Ordering, ptr}; +use core::{cell::Cell, cmp::Ordering, ptr}; use crate::utility_types::Delta; diff --git a/src/syntax_text.rs b/src/syntax_text.rs index 7e91ba2..40f8433 100644 --- a/src/syntax_text.rs +++ b/src/syntax_text.rs @@ -1,4 +1,5 @@ -use std::fmt; +use alloc::string::{String, ToString}; +use core::{cmp, fmt}; use crate::{ TextRange, TextSize, @@ -202,7 +203,7 @@ fn zip_texts>(xs: &mut I, ys: &mut if !(x_text.starts_with(y_text) || y_text.starts_with(x_text)) { return Some(()); } - let advance = std::cmp::min(x.1.len(), y.1.len()); + let advance = cmp::min(x.1.len(), y.1.len()); x.1 = TextRange::new(x.1.start() + advance, x.1.end()); y.1 = TextRange::new(y.1.start() + advance, y.1.end()); } @@ -211,7 +212,7 @@ fn zip_texts>(xs: &mut I, ys: &mut impl Eq for SyntaxText {} mod private { - use std::ops; + use core::ops; use crate::{TextRange, TextSize}; diff --git a/src/text_size.rs b/src/text_size.rs new file mode 100644 index 0000000..1af12b7 --- /dev/null +++ b/src/text_size.rs @@ -0,0 +1,470 @@ +use alloc::string::String; +use core::{ + cmp::{self, Ordering}, + convert::{TryFrom, TryInto}, + fmt, iter, + num::TryFromIntError, + ops::{Add, AddAssign, Bound, Index, IndexMut, Range, RangeBounds, Sub, SubAssign}, +}; + +#[cfg(target_pointer_width = "16")] +compile_error!("text-size assumes usize >= u32 and does not work on 16-bit targets"); + +#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct TextSize { + raw: u32, +} + +impl fmt::Debug for TextSize { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.raw) + } +} + +impl TextSize { + #[inline] + pub const fn new(raw: u32) -> TextSize { + TextSize { raw } + } + + #[inline] + pub fn of(text: T) -> TextSize { + text.text_len() + } + + #[inline] + pub const fn checked_add(self, rhs: TextSize) -> Option { + match self.raw.checked_add(rhs.raw) { + Some(raw) => Some(TextSize { raw }), + None => None, + } + } + + #[inline] + pub const fn checked_sub(self, rhs: TextSize) -> Option { + match self.raw.checked_sub(rhs.raw) { + Some(raw) => Some(TextSize { raw }), + None => None, + } + } +} + +impl From for TextSize { + #[inline] + fn from(raw: u32) -> Self { + TextSize { raw } + } +} + +impl From for u32 { + #[inline] + fn from(value: TextSize) -> Self { + value.raw + } +} + +impl TryFrom for TextSize { + type Error = TryFromIntError; + + #[inline] + fn try_from(value: usize) -> Result { + Ok(u32::try_from(value)?.into()) + } +} + +impl From for usize { + #[inline] + fn from(value: TextSize) -> Self { + value.raw as usize + } +} + +macro_rules! text_size_ops { + (impl $op:ident for TextSize by fn $fn:ident = $symbol:tt) => { + impl $op for TextSize { + type Output = TextSize; + + #[inline] + fn $fn(self, other: TextSize) -> TextSize { + TextSize { raw: self.raw $symbol other.raw } + } + } + + impl $op<&TextSize> for TextSize { + type Output = TextSize; + + #[inline] + fn $fn(self, other: &TextSize) -> TextSize { + self $symbol *other + } + } + + impl $op for &TextSize + where + TextSize: $op, + { + type Output = TextSize; + + #[inline] + fn $fn(self, other: T) -> TextSize { + *self $symbol other + } + } + }; +} + +text_size_ops!(impl Add for TextSize by fn add = +); +text_size_ops!(impl Sub for TextSize by fn sub = -); + +impl AddAssign for TextSize +where + TextSize: Add, +{ + #[inline] + fn add_assign(&mut self, rhs: A) { + *self = *self + rhs; + } +} + +impl SubAssign for TextSize +where + TextSize: Sub, +{ + #[inline] + fn sub_assign(&mut self, rhs: S) { + *self = *self - rhs; + } +} + +impl iter::Sum for TextSize +where + TextSize: Add, +{ + #[inline] + fn sum>(iter: I) -> TextSize { + iter.fold(0.into(), Add::add) + } +} + +#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)] +pub struct TextRange { + start: TextSize, + end: TextSize, +} + +impl fmt::Debug for TextRange { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}..{}", self.start().raw, self.end().raw) + } +} + +impl TextRange { + #[inline] + pub const fn new(start: TextSize, end: TextSize) -> TextRange { + assert!(start.raw <= end.raw); + TextRange { start, end } + } + + #[inline] + pub const fn at(offset: TextSize, len: TextSize) -> TextRange { + TextRange::new(offset, TextSize::new(offset.raw + len.raw)) + } + + #[inline] + pub const fn empty(offset: TextSize) -> TextRange { + TextRange { start: offset, end: offset } + } + + #[inline] + pub const fn up_to(end: TextSize) -> TextRange { + TextRange { start: TextSize::new(0), end } + } + + #[inline] + pub const fn start(self) -> TextSize { + self.start + } + + #[inline] + pub const fn end(self) -> TextSize { + self.end + } + + #[inline] + pub const fn len(self) -> TextSize { + TextSize { raw: self.end().raw - self.start().raw } + } + + #[inline] + pub const fn is_empty(self) -> bool { + self.start().raw == self.end().raw + } + + #[inline] + pub fn contains(self, offset: TextSize) -> bool { + self.start() <= offset && offset < self.end() + } + + #[inline] + pub fn contains_inclusive(self, offset: TextSize) -> bool { + self.start() <= offset && offset <= self.end() + } + + #[inline] + pub fn contains_range(self, other: TextRange) -> bool { + self.start() <= other.start() && other.end() <= self.end() + } + + #[inline] + pub fn intersect(self, other: TextRange) -> Option { + let start = cmp::max(self.start(), other.start()); + let end = cmp::min(self.end(), other.end()); + if end < start { + return None; + } + Some(TextRange::new(start, end)) + } + + #[inline] + pub fn cover(self, other: TextRange) -> TextRange { + let start = cmp::min(self.start(), other.start()); + let end = cmp::max(self.end(), other.end()); + TextRange::new(start, end) + } + + #[inline] + pub fn cover_offset(self, offset: TextSize) -> TextRange { + self.cover(TextRange::empty(offset)) + } + + #[inline] + pub fn checked_add(self, offset: TextSize) -> Option { + Some(TextRange { + start: self.start.checked_add(offset)?, + end: self.end.checked_add(offset)?, + }) + } + + #[inline] + pub fn checked_sub(self, offset: TextSize) -> Option { + Some(TextRange { + start: self.start.checked_sub(offset)?, + end: self.end.checked_sub(offset)?, + }) + } + + #[inline] + pub fn ordering(self, other: TextRange) -> Ordering { + if self.end() <= other.start() { + Ordering::Less + } else if other.end() <= self.start() { + Ordering::Greater + } else { + Ordering::Equal + } + } +} + +impl Index for str { + type Output = str; + + #[inline] + fn index(&self, index: TextRange) -> &str { + &self[Range::::from(index)] + } +} + +impl Index for String { + type Output = str; + + #[inline] + fn index(&self, index: TextRange) -> &str { + &self[Range::::from(index)] + } +} + +impl IndexMut for str { + #[inline] + fn index_mut(&mut self, index: TextRange) -> &mut str { + &mut self[Range::::from(index)] + } +} + +impl IndexMut for String { + #[inline] + fn index_mut(&mut self, index: TextRange) -> &mut str { + &mut self[Range::::from(index)] + } +} + +impl RangeBounds for TextRange { + fn start_bound(&self) -> Bound<&TextSize> { + Bound::Included(&self.start) + } + + fn end_bound(&self) -> Bound<&TextSize> { + Bound::Excluded(&self.end) + } +} + +impl From for Range +where + T: From, +{ + #[inline] + fn from(range: TextRange) -> Self { + range.start().into()..range.end().into() + } +} + +macro_rules! text_range_ops { + (impl $op:ident for TextRange by fn $fn:ident = $symbol:tt) => { + impl $op<&TextSize> for TextRange { + type Output = TextRange; + + #[inline] + fn $fn(self, other: &TextSize) -> TextRange { + self $symbol *other + } + } + + impl $op for &TextRange + where + TextRange: $op, + { + type Output = TextRange; + + #[inline] + fn $fn(self, other: T) -> TextRange { + *self $symbol other + } + } + }; +} + +impl Add for TextRange { + type Output = TextRange; + + #[inline] + fn add(self, offset: TextSize) -> TextRange { + self.checked_add(offset).expect("TextRange +offset overflowed") + } +} + +impl Sub for TextRange { + type Output = TextRange; + + #[inline] + fn sub(self, offset: TextSize) -> TextRange { + self.checked_sub(offset).expect("TextRange -offset overflowed") + } +} + +text_range_ops!(impl Add for TextRange by fn add = +); +text_range_ops!(impl Sub for TextRange by fn sub = -); + +impl AddAssign for TextRange +where + TextRange: Add, +{ + #[inline] + fn add_assign(&mut self, rhs: A) { + *self = *self + rhs; + } +} + +impl SubAssign for TextRange +where + TextRange: Sub, +{ + #[inline] + fn sub_assign(&mut self, rhs: S) { + *self = *self - rhs; + } +} + +pub trait TextLen: Copy + private::Sealed { + fn text_len(self) -> TextSize; +} + +mod private { + pub trait Sealed {} +} + +impl private::Sealed for &'_ str {} + +impl TextLen for &'_ str { + #[inline] + fn text_len(self) -> TextSize { + self.len().try_into().unwrap() + } +} + +impl private::Sealed for &'_ String {} + +impl TextLen for &'_ String { + #[inline] + fn text_len(self) -> TextSize { + self.as_str().text_len() + } +} + +impl private::Sealed for char {} + +impl TextLen for char { + #[inline] + fn text_len(self) -> TextSize { + (self.len_utf8() as u32).into() + } +} + +#[cfg(feature = "serde1")] +mod serde_impls { + use serde::{Deserialize, Deserializer, Serialize, Serializer, de}; + + use crate::{TextRange, TextSize}; + + impl Serialize for TextSize { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + u32::from(*self).serialize(serializer) + } + } + + impl<'de> Deserialize<'de> for TextSize { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + u32::deserialize(deserializer).map(TextSize::from) + } + } + + impl Serialize for TextRange { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + (self.start(), self.end()).serialize(serializer) + } + } + + impl<'de> Deserialize<'de> for TextRange { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let (start, end) = <(TextSize, TextSize)>::deserialize(deserializer)?; + if start > end { + return Err(de::Error::custom(alloc::format!( + "invalid range: {:?}..{:?}", + start, + end + ))); + } + Ok(TextRange::new(start, end)) + } + } +} diff --git a/src/utility_types.rs b/src/utility_types.rs index 656f9d4..86af1b5 100644 --- a/src/utility_types.rs +++ b/src/utility_types.rs @@ -1,8 +1,9 @@ -use std::{ - fmt, +use core::{ + fmt, mem, ops::{AddAssign, Deref}, }; -use text_size::TextSize; + +use crate::TextSize; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum NodeOrToken { @@ -125,7 +126,7 @@ impl Iterator for TokenAtOffset { type Item = T; fn next(&mut self) -> Option { - match std::mem::replace(self, TokenAtOffset::None) { + match mem::replace(self, TokenAtOffset::None) { TokenAtOffset::None => None, TokenAtOffset::Single(node) => { *self = TokenAtOffset::None;