strop_core/
diagnostics.rs1use crate::Buffer;
3use serde::Serialize;
4use std::sync::atomic::{AtomicU64, Ordering};
5use strop_trace::{capture_content, enabled, record, EventKind};
6
7static NEXT_BUFFER: AtomicU64 = AtomicU64::new(1);
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
10#[serde(transparent)]
11pub struct BufferTraceId(u64);
12impl BufferTraceId {
13 pub(crate) fn next() -> Self {
14 Self(NEXT_BUFFER.fetch_add(1, Ordering::Relaxed))
15 }
16}
17
18#[derive(Serialize)]
19struct Mutation<'a> {
20 buffer: BufferTraceId,
21 source: crate::ChangeOrigin,
22 revision: u64,
23 start_byte: usize,
24 removed_bytes: usize,
25 inserted_bytes: usize,
26 #[serde(skip_serializing_if = "Option::is_none")]
27 inserted_text: Option<&'a str>,
28}
29
30impl Buffer {
31 pub fn trace_id(&self) -> BufferTraceId {
32 self.trace_identity
33 }
34
35 pub(crate) fn trace_edit(
36 &self,
37 source: crate::ChangeOrigin,
38 start_byte: usize,
39 removed_bytes: usize,
40 inserted: &str,
41 ) {
42 if !enabled() {
43 return;
44 }
45 record(
46 EventKind::Mutation,
47 &Mutation {
48 buffer: self.trace_id(),
49 source,
50 revision: self.revision().get(),
51 start_byte,
52 removed_bytes,
53 inserted_bytes: inserted.len(),
54 inserted_text: capture_content().then_some(inserted),
55 },
56 );
57 }
58
59 pub(crate) fn trace_snapshot(&self, removed_bytes: usize) {
60 if !enabled() {
61 return;
62 }
63 let text = capture_content().then(|| self.text().to_string());
64 record(
65 EventKind::Mutation,
66 &Mutation {
67 buffer: self.trace_id(),
68 source: crate::ChangeOrigin::System,
69 revision: self.revision().get(),
70 start_byte: 0,
71 removed_bytes,
72 inserted_bytes: self.len_bytes(),
73 inserted_text: text.as_deref(),
74 },
75 );
76 }
77
78 pub(crate) fn trace_history(&self, edits: &[crate::history::Edit]) {
79 if !enabled() {
80 return;
81 }
82 #[derive(Serialize)]
83 struct HistoryEdit<'a> {
84 start_byte: usize,
85 bytes: usize,
86 kind: crate::history::EditKind,
87 #[serde(skip_serializing_if = "Option::is_none")]
88 text: Option<&'a str>,
89 }
90 #[derive(Serialize)]
91 struct AppliedHistory<'a> {
92 buffer: BufferTraceId,
93 revision: u64,
94 edits: Vec<HistoryEdit<'a>>,
95 }
96 record(
97 EventKind::History,
98 &AppliedHistory {
99 buffer: self.trace_id(),
100 revision: self.revision().get(),
101 edits: edits
102 .iter()
103 .map(|edit| HistoryEdit {
104 start_byte: edit.at,
105 bytes: edit.text.len(),
106 kind: edit.kind,
107 text: capture_content().then_some(edit.text.as_str()),
108 })
109 .collect(),
110 },
111 );
112 }
113}