implement custom serialize for Span
This commit is contained in:
parent
a91b6f82f5
commit
124d3383e8
|
@ -145,7 +145,7 @@ impl SourceFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a range of characters in a source file.
|
/// Represents a range of characters in a source file.
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
|
||||||
#[derive(Clone, Getters, CopyGetters)]
|
#[derive(Clone, Getters, CopyGetters)]
|
||||||
pub struct Span {
|
pub struct Span {
|
||||||
/// Get the start byte index of the span.
|
/// Get the start byte index of the span.
|
||||||
|
|
|
@ -20,6 +20,12 @@ pub mod lexical;
|
||||||
pub mod syntax;
|
pub mod syntax;
|
||||||
pub mod transpile;
|
pub mod transpile;
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
mod serde;
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
#[cfg_attr(feature = "serde", doc(inline))]
|
||||||
|
pub use serde::SerdeWrapper;
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use base::{source_file::SourceFile, Error, FileProvider, Handler, Result};
|
use base::{source_file::SourceFile, Error, FileProvider, Handler, Result};
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
//! Utilities for (de-)serializing
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
sync::{Arc, LazyLock, Mutex, RwLock},
|
||||||
|
};
|
||||||
|
|
||||||
|
use serde::{de::{self, Visitor}, ser::SerializeStruct, Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::base::source_file::{SourceFile, Span};
|
||||||
|
|
||||||
|
static SERIALIZE_DATA: LazyLock<Mutex<SerializeData>> =
|
||||||
|
LazyLock::new(|| Mutex::new(SerializeData::default()));
|
||||||
|
|
||||||
|
static DEDUPLICATE_SOURCE_FILES: LazyLock<RwLock<bool>> = LazyLock::new(|| RwLock::new(false));
|
||||||
|
|
||||||
|
/// Wrapper to remove duplicate source file data during (de-)serialization
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SerdeWrapper<T>(pub T);
|
||||||
|
|
||||||
|
impl<T> Serialize for SerdeWrapper<T>
|
||||||
|
where
|
||||||
|
T: Serialize,
|
||||||
|
{
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
*DEDUPLICATE_SOURCE_FILES.write().unwrap() = true;
|
||||||
|
SERIALIZE_DATA.lock().unwrap().clear();
|
||||||
|
let mut s = serializer.serialize_struct("SourceFileWrapper", 2)?;
|
||||||
|
s.serialize_field("data", &self.0)?;
|
||||||
|
*DEDUPLICATE_SOURCE_FILES.write().unwrap() = false;
|
||||||
|
s.serialize_field(
|
||||||
|
"source_files",
|
||||||
|
&SERIALIZE_DATA.lock().unwrap().id_to_source_file,
|
||||||
|
)?;
|
||||||
|
s.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Internally used for Serialization
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
struct SerializeData {
|
||||||
|
id_counter: usize,
|
||||||
|
ptr_to_id: HashMap<usize, usize>,
|
||||||
|
id_to_source_file: HashMap<usize, SourceFile>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SerializeData {
|
||||||
|
fn clear(&mut self) {
|
||||||
|
self.id_counter = 0;
|
||||||
|
self.id_to_source_file.clear();
|
||||||
|
self.ptr_to_id.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get id of already stored [`Arc`] or store it and return new id
|
||||||
|
pub fn get_id_of(&mut self, source_file: &Arc<SourceFile>) -> usize {
|
||||||
|
let ptr = Arc::as_ptr(source_file);
|
||||||
|
if let Some(&id) = self.ptr_to_id.get(&(ptr as usize)) {
|
||||||
|
id
|
||||||
|
} else {
|
||||||
|
let id = self.id_counter;
|
||||||
|
self.id_counter += 1;
|
||||||
|
|
||||||
|
self.ptr_to_id.insert(ptr as usize, id);
|
||||||
|
self.id_to_source_file
|
||||||
|
.insert(id, Arc::unwrap_or_clone(source_file.to_owned()));
|
||||||
|
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for Span {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
let mut s = serializer.serialize_struct("Span", 3)?;
|
||||||
|
s.serialize_field("start", &self.start())?;
|
||||||
|
s.serialize_field("end", &self.end())?;
|
||||||
|
|
||||||
|
if *DEDUPLICATE_SOURCE_FILES.read().unwrap() {
|
||||||
|
let mut data = SERIALIZE_DATA.lock().unwrap();
|
||||||
|
s.serialize_field("source_file", &data.get_id_of(self.source_file()))?;
|
||||||
|
} else {
|
||||||
|
s.serialize_field("source_file", self.source_file())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
s.end()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue