Detailed changes
@@ -1094,7 +1094,7 @@ impl TextThread {
.buffer
.read(cx)
.version
- .observed(anchor.start.timestamp),
+ .observed(anchor.start.timestamp()),
TextThreadOperation::UpdateMessage { message_id, .. } => {
self.messages_metadata.contains_key(message_id)
}
@@ -1121,10 +1121,11 @@ impl TextThread {
cx: &App,
) -> bool {
let version = &self.buffer.read(cx).version;
- let observed_start =
- range.start.is_min() || range.start.is_max() || version.observed(range.start.timestamp);
+ let observed_start = range.start.is_min()
+ || range.start.is_max()
+ || version.observed(range.start.timestamp());
let observed_end =
- range.end.is_min() || range.end.is_max() || version.observed(range.end.timestamp);
+ range.end.is_min() || range.end.is_max() || version.observed(range.end.timestamp());
observed_start && observed_end
}
@@ -251,9 +251,10 @@ pub fn serialize_diagnostics<'a>(
/// Serializes an [`Anchor`] to be sent over RPC.
pub fn serialize_anchor(anchor: &Anchor) -> proto::Anchor {
+ let timestamp = anchor.timestamp();
proto::Anchor {
- replica_id: anchor.timestamp.replica_id.as_u16() as u32,
- timestamp: anchor.timestamp.value,
+ replica_id: timestamp.replica_id.as_u16() as u32,
+ timestamp: timestamp.value,
offset: anchor.offset as u64,
bias: match anchor.bias {
Bias::Left => proto::Bias::Left as i32,
@@ -485,18 +486,20 @@ pub fn deserialize_anchor(anchor: proto::Anchor) -> Option<Anchor> {
} else {
None
};
- Some(Anchor {
- timestamp: clock::Lamport {
- replica_id: ReplicaId::new(anchor.replica_id as u16),
- value: anchor.timestamp,
- },
- offset: anchor.offset as usize,
- bias: match proto::Bias::from_i32(anchor.bias)? {
- proto::Bias::Left => Bias::Left,
- proto::Bias::Right => Bias::Right,
- },
+ let timestamp = clock::Lamport {
+ replica_id: ReplicaId::new(anchor.replica_id as u16),
+ value: anchor.timestamp,
+ };
+ let bias = match proto::Bias::from_i32(anchor.bias)? {
+ proto::Bias::Left => Bias::Left,
+ proto::Bias::Right => Bias::Right,
+ };
+ Some(Anchor::new(
+ timestamp,
+ anchor.offset as usize,
+ bias,
buffer_id,
- })
+ ))
}
/// Returns a `[clock::Lamport`] timestamp for the given [`proto::Operation`].
@@ -5598,7 +5598,7 @@ impl LspStore {
buffer
.update(cx, |buffer, _| {
- buffer.wait_for_edits(Some(position.timestamp))
+ buffer.wait_for_edits(Some(position.timestamp()))
})
.await?;
this.update(cx, |this, cx| {
@@ -9,9 +9,15 @@ use sum_tree::{Bias, Dimensions};
#[doc(alias = "TextAnchor")]
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub struct Anchor {
- /// The timestamp of the operation that inserted the text
- /// in which this anchor is located.
- pub timestamp: clock::Lamport,
+ // /// The timestamp of the operation that inserted the text
+ // /// in which this anchor is located.
+ // pub(crate) timestamp: clock::Lamport,
+ // we store the replica id and sequence number of the timestamp inline
+ // to avoid the alignment of our fields from increasing the size of this struct
+ // This saves 8 bytes, by allowing replica id, value and bias to occupy the padding
+ timestamp_replica_id: clock::ReplicaId,
+ timestamp_value: clock::Seq,
+
/// The byte offset into the text inserted in the operation
/// at `timestamp`.
pub offset: usize,
@@ -31,7 +37,7 @@ impl Debug for Anchor {
}
f.debug_struct("Anchor")
- .field("timestamp", &self.timestamp)
+ .field("timestamp", &self.timestamp())
.field("offset", &self.offset)
.field("bias", &self.bias)
.field("buffer_id", &self.buffer_id)
@@ -41,22 +47,40 @@ impl Debug for Anchor {
impl Anchor {
pub const MIN: Self = Self {
- timestamp: clock::Lamport::MIN,
+ timestamp_replica_id: clock::Lamport::MIN.replica_id,
+ timestamp_value: clock::Lamport::MIN.value,
offset: usize::MIN,
bias: Bias::Left,
buffer_id: None,
};
pub const MAX: Self = Self {
- timestamp: clock::Lamport::MAX,
+ timestamp_replica_id: clock::Lamport::MAX.replica_id,
+ timestamp_value: clock::Lamport::MAX.value,
offset: usize::MAX,
bias: Bias::Right,
buffer_id: None,
};
+ pub fn new(
+ timestamp: clock::Lamport,
+ offset: usize,
+ bias: Bias,
+ buffer_id: Option<BufferId>,
+ ) -> Self {
+ Self {
+ timestamp_replica_id: timestamp.replica_id,
+ timestamp_value: timestamp.value,
+ offset,
+ bias,
+ buffer_id,
+ }
+ }
+
pub fn min_for_buffer(buffer_id: BufferId) -> Self {
Self {
- timestamp: clock::Lamport::MIN,
+ timestamp_replica_id: clock::Lamport::MIN.replica_id,
+ timestamp_value: clock::Lamport::MIN.value,
offset: usize::MIN,
bias: Bias::Left,
buffer_id: Some(buffer_id),
@@ -65,7 +89,8 @@ impl Anchor {
pub fn max_for_buffer(buffer_id: BufferId) -> Self {
Self {
- timestamp: clock::Lamport::MAX,
+ timestamp_replica_id: clock::Lamport::MAX.replica_id,
+ timestamp_value: clock::Lamport::MAX.value,
offset: usize::MAX,
bias: Bias::Right,
buffer_id: Some(buffer_id),
@@ -85,7 +110,7 @@ impl Anchor {
}
pub fn cmp(&self, other: &Anchor, buffer: &BufferSnapshot) -> Ordering {
- let fragment_id_comparison = if self.timestamp == other.timestamp {
+ let fragment_id_comparison = if self.timestamp() == other.timestamp() {
Ordering::Equal
} else {
buffer
@@ -164,16 +189,24 @@ impl Anchor {
}
pub fn is_min(&self) -> bool {
- self.timestamp == clock::Lamport::MIN
+ self.timestamp() == clock::Lamport::MIN
&& self.offset == usize::MIN
&& self.bias == Bias::Left
}
pub fn is_max(&self) -> bool {
- self.timestamp == clock::Lamport::MAX
+ self.timestamp() == clock::Lamport::MAX
&& self.offset == usize::MAX
&& self.bias == Bias::Right
}
+
+ #[inline]
+ pub fn timestamp(&self) -> clock::Lamport {
+ clock::Lamport {
+ replica_id: self.timestamp_replica_id,
+ value: self.timestamp_value,
+ }
+ }
}
pub trait OffsetRangeExt {
@@ -1657,10 +1657,10 @@ impl Buffer {
) -> impl 'static + Future<Output = Result<()>> + use<It> {
let mut futures = Vec::new();
for anchor in anchors {
- if !self.version.observed(anchor.timestamp) && !anchor.is_max() && !anchor.is_min() {
+ if !self.version.observed(anchor.timestamp()) && !anchor.is_max() && !anchor.is_min() {
let (tx, rx) = oneshot::channel();
self.edit_id_resolvers
- .entry(anchor.timestamp)
+ .entry(anchor.timestamp())
.or_default()
.push(tx);
futures.push(rx);
@@ -2275,7 +2275,7 @@ impl BufferSnapshot {
};
assert_eq!(
insertion.timestamp,
- anchor.timestamp,
+ anchor.timestamp(),
"invalid insertion for buffer {}@{:?} and anchor {:?}",
self.remote_id(),
self.version,
@@ -2309,13 +2309,14 @@ impl BufferSnapshot {
} else {
debug_assert_eq!(anchor.buffer_id, Some(self.remote_id));
debug_assert!(
- self.version.observed(anchor.timestamp),
+ self.version.observed(anchor.timestamp()),
"Anchor timestamp {:?} not observed by buffer {:?}",
- anchor.timestamp,
+ anchor.timestamp(),
self.version
);
let item = self.try_find_fragment(anchor);
- let Some(insertion) = item.filter(|insertion| insertion.timestamp == anchor.timestamp)
+ let Some(insertion) =
+ item.filter(|insertion| insertion.timestamp == anchor.timestamp())
else {
self.panic_bad_anchor(anchor);
};
@@ -2343,7 +2344,7 @@ impl BufferSnapshot {
"invalid anchor - buffer id does not match: anchor {anchor:?}; buffer id: {}, version: {:?}",
self.remote_id, self.version
);
- } else if !self.version.observed(anchor.timestamp) {
+ } else if !self.version.observed(anchor.timestamp()) {
panic!(
"invalid anchor - snapshot has not observed lamport: {:?}; version: {:?}",
anchor, self.version
@@ -2369,7 +2370,7 @@ impl BufferSnapshot {
} else {
let item = self.try_find_fragment(anchor);
item.filter(|insertion| {
- !cfg!(debug_assertions) || insertion.timestamp == anchor.timestamp
+ !cfg!(debug_assertions) || insertion.timestamp == anchor.timestamp()
})
.map(|insertion| &insertion.fragment_id)
}
@@ -2377,7 +2378,7 @@ impl BufferSnapshot {
fn try_find_fragment(&self, anchor: &Anchor) -> Option<&InsertionFragment> {
let anchor_key = InsertionFragmentKey {
- timestamp: anchor.timestamp,
+ timestamp: anchor.timestamp(),
split_offset: anchor.offset,
};
match self.insertions.find_with_prev::<InsertionFragmentKey, _>(
@@ -2453,19 +2454,20 @@ impl BufferSnapshot {
return Anchor::max_for_buffer(self.remote_id);
};
let overshoot = offset - start;
- Anchor {
- timestamp: fragment.timestamp,
- offset: fragment.insertion_offset + overshoot,
+ Anchor::new(
+ fragment.timestamp,
+ fragment.insertion_offset + overshoot,
bias,
- buffer_id: Some(self.remote_id),
- }
+ Some(self.remote_id),
+ )
}
}
pub fn can_resolve(&self, anchor: &Anchor) -> bool {
anchor.is_min()
|| anchor.is_max()
- || (Some(self.remote_id) == anchor.buffer_id && self.version.observed(anchor.timestamp))
+ || (Some(self.remote_id) == anchor.buffer_id
+ && self.version.observed(anchor.timestamp()))
}
pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize {
@@ -2760,18 +2762,18 @@ impl<D: TextDimension + Ord, F: FnMut(&FragmentSummary) -> bool> Iterator for Ed
break;
}
- let start_anchor = Anchor {
- timestamp: fragment.timestamp,
- offset: fragment.insertion_offset,
- bias: Bias::Right,
- buffer_id: Some(self.buffer_id),
- };
- let end_anchor = Anchor {
- timestamp: fragment.timestamp,
- offset: fragment.insertion_offset + fragment.len,
- bias: Bias::Left,
- buffer_id: Some(self.buffer_id),
- };
+ let start_anchor = Anchor::new(
+ fragment.timestamp,
+ fragment.insertion_offset,
+ Bias::Right,
+ Some(self.buffer_id),
+ );
+ let end_anchor = Anchor::new(
+ fragment.timestamp,
+ fragment.insertion_offset + fragment.len,
+ Bias::Left,
+ Some(self.buffer_id),
+ );
if !fragment.was_visible(self.since, self.undos) && fragment.visible {
let mut visible_end = cursor.end().visible;